Image courtesy of the NCAA

1 Introduction

This project will build on one that I began in March of 2025, predicting the outcomes of March Madness tournament games. March Madness is a single-elimination basketball tournament featuring 68 teams, with representatives from every conference in Division I NCAA basketball. The 68-team pool is narrowed down to 64 after eight teams play each other in the “First Four” round. Within this field of 64, they’re split between four “regions” of a bracket, South, West, East, and Midwest. The teams in each region are ranked by the NCAA Committee and given a “seed” between #1 and #16. Those teams are then matched up against each other so that #1 plays #16, #2 plays #15, #3 plays #14, and so on. We’ll revisit the seeding and team breakdown later, but this should give those unfamiliar with the tournament a general idea of the format.

Each year, once the field of 64 is established, tens of millions around the world try their best to predict the winners and losers of each game across all 67 that are played throughout the tournament, which narrows the field down to just two teams who will play for the National Championship title. To this day, nobody has ever correctly predicted all 67 outcomes perfectly. According to the NCAA, the closest anyone has ever come to a perfect bracket was Gregg Nigl, a neuropsychologist from Columbus, Ohio who correctly predicted the outcomes of 49 straight games before #3 Purdue defeated #2 Tennessee in overtime of the second game in the Sweet 16.

This year, I decided to take a more analytical approach to building my own bracket. After three days of researching predictive values in basketball, reading papers, and journaling all of my findings, I found a blog post from 2021 about an R Project using a binomial distribution approach I hadn’t seen anywhere else before. I tried my best to emulate that procedure with my limited abilities at the time, but in the end was unsatisfied with the uncertain quality of my work. I elected not to embarrass myself by subjecting this model to the scrutiny of my peers, and kept the results buried in an almost indecipherable spreadsheet. This uncertainty proved to be foolish, however, as all of that work done exclusively in Microsoft Excel and several pages of handwritten notes was able to correctly predict 56/67 outcomes across the entire tournament. The goal, unfortunately, is a perfect 67/67. This challenge has stumped mathematicians, economists, analysts, and everyday basketball fans alike for decades. The question that everyone asks each March is the same, “what teams are going to pull off an upset?”

If choosing a perfect bracket were as simple as picking the “favorite” in each game by their seeding, we’d expect to see a Final Four of four #1 seeds every year, but we know that’s not the case. In fact, it’s only happened twice: 2008’s Final Four featured #1 seeds Kansas, Memphis, North Carolina, and UCLA. The only other year it’s happened? 2025. This year’s Final Four of #1 seeds Auburn, Duke, Florida, and Houston achieved that feat for just the second time ever. Despite this, we enter the 2025-26 College Basketball season with nobody ever correctly crafting a perfect bracket.

So, what teams pulled off an “upset”? To answer that question we first need to split it into two parts. Which teams were actually favored in each game, and who won? The latter is easy to answer, as each game was played in March/April of 2025, and we have all the results readily available. The former, not so much. In order to start answering that question, let’s set the stage.


2 The Bracket

Each team in the March Madness tournament is vying for a chance to play in the National Championship. Those 68 teams are selected from the pool of all 364 Division I teams in the NCAA. Each of the 364 schools are split into 31 different conferences, who primarily compete against the other members of their conference in the regular season. At the conclusion of the regular season each conference hosts their own single-elimination tournament, and the winner of that tournament receives an “automatic bid” to play in the March Madness tournament. The remaining 37 spots in the tournament are decided by the NCAA Committee, who awards “at-large” bids. These go to whichever teams they deem to be the 37 best in the country, but didn’t win their conference and receive an automatic bid.

For a number of reasons, this selection process is where the “madness” begins. Any team in the country, regardless of how bad they were throughout the regular season, just needs to qualify for their conference tournament to have a shot at dancing. If they can get hot in their conference tournament and win it, they receive an automatic bid all the same. We’ll take a look at the data in the next section and where it comes from, but one of the “worst” teams in the tournament this year, the Saint Francis Red Flash, had a pedestrian 13-17 overall record heading into the Northeast Conference (NEC) Tournament. Despite this, they were able to secure wins over Wagner, LIU, and Central Connecticut to win the NEC and punch their ticket to be a part of the madness.

As we can see, the auto-bid system introduces a level of chaos in terms of who is able to qualify for the tournament. Mount St. Mary’s, another auto-bid team out of the MAAC (Metro Atlantic Athletic Conference) was matched up with blue-blood basketball program Duke in the Round of 64. With an undergraduate student body of 1,815, Mount St. Mary’s has absolutely no business playing Duke in a nationally televised basketball game, and suffered an uncompetitive 93-49 defeat. Despite the clear discrepancies in some matchups, the auto-bid system affords the smaller conferences/schools an equal opportunity to make an appearance in the tournament.

When a national powerhouse like Duke squares off against a small, private, liberal arts school from rural Maryland, we can reasonably assume who’s going to win that game. While that’s not always the case (see 2018 #1 Virginia vs. #16 UMBC, another #16 seed from Maryland who achieved a much different result), we generally expect the smaller conferences to struggle against their much larger counterparts. The at-large bid system, on the other hand, introduces a considerable amount of uncertainty to the bracket for a different reason. The NCAA Committee’s exact approach to determining the 37 “best” remaining schools in the country, after all the auto-bids have been awarded, has been the subject of much debate throughout the tournament’s entire existence. We can reasonably assume that they use much of the same criteria that we will use in our own data, but they have an illustrious history of being “wrong” when making those selections. Since the selection process of at-large bids isn’t the topic of this project, we won’t go too in-depth into who receives them. All we need to understand about these at-large teams is that they are believed to have earned their bid through their play across the entire season, and their seeding should reflect how good of a team they are. For instance, Auburn lost in the semifinals of the SEC (Southeastern Conference) Tournament to Tennessee. After they both received at-large bids, Auburn was given a #1 seed, Tennessee a #2 seed.


3 The Data

Now that we have a general understanding of what sort of teams make the tournament, let’s take a look at the data we’ll be using. The first, most important dataset we have at our disposal is Ken Pomeroy’s KenPom rankings. These are the numbers we’ll be using to do most of our score predictions. As per the Terms of Use for this data, here is a link to the KenPom Website.

# We use the tidyverse and DT packages to display our data in a cleaner format as we work through it 
# all. We also use the tidyverse much later in the report to create some useful graphs to draw insights 
# about our data.
library(tidyverse)
library(DT)
# I initially used dplyr for some data transforming steps, but now it exists only to interact with our 
# DT package, 
library(dplyr)
# This was a package I found by accidentally confusing Python and R syntax, but it's incredibly useful 
# for displaying the results of our prediction model that we'll be using quite a bit later. 
library(glue)
# In order to point out a number of teams in the plots we'll be building to try and set apart some 
# specific winners and losers, we use gghighlight to make them stand out amongst the entire field of 64
library(gghighlight)
library(cbbplotR)

# Reads in our first dataset and formats it nicely into a readable datatable
kp <- read_csv('kenpom.csv', col_names=TRUE)
data(kp, package='ggplot2')
datatable(kp, 
          extensions='Scroller',
          options = list(scrollX=TRUE))


There’s a few variables in this data that we don’t need, so we can safely get rid of them. The only numbers we’ll be using for now are ORtg, DRtg, and AdjT. It may not seem like much, but these values represent almost all we need to make some surprisingly accurate assumptions about how these games will go.

  • ORtg - A measure of opponent-adjusted offensive efficiency, how many points a team scores per 100 possessions.

  • DRtg - A measure of opponent-adjusted defensive efficiency, how many points a team allows per 100 possessions.

  • AdjT - A measure of opponent-adjusted “tempo,” how many possessions a team has per 40 minutes.


# Renames some of the variables we need that shared duplicate headers with others
kp1 <- kp |>
  rename(ORtg = ORtg...6, DRtg = DRtg...7)

# Removes the variables we don't need for this particular analysis
kp2 <- kp1 |>
  select(-(Conf:NetRtg...5), -(Luck:NetRtg...13))

# Once again uses the DT package to display our data in a readable datatable
data(kp2, package='ggplot2')
datatable(kp2, 
          extensions='Scroller',
          options = list(scrollX=TRUE))


Before we move on, we’re going to need a few averages from this data to be used later as well . Each of them will be discussed later, but for now the averages we need are:

  • AdjTncaa

  • eFGOncaa

  • eFGDncaa

  • DRtgncaa

  • pppncaa

eFGOncaa and eFGDncaa are two figures I calculated separately outside of this work and have on hand, so I’ll be assigning those values manually. They come from TeamRankings, which is introduced below.

# Finding / assigning all of the average values we'll need later

AdjTncaa <- mean(kp2$AdjT)

eFGOncaa <- 0.5076

eFGDncaa <- 0.5096

DRtgncaa <- mean(kp2$DRtg)

pppOncaa <- mean(kp2$ORtg / 100)


Now that we have the KenPom data, we’re going to need some more team-specific data. These are all numbers that I collected manually, team by team, in March from the official NCAA Statistics website and TeamRankings, and they’re already subset to just the teams that played in the 2025 March Madness tournament. Since we only want to look at this subset data, we can use an inner join to get the almost complete, correctly subset data we need containing just the 68 teams in the tournament this year.


# Reads in our team statistics and joins it with our kenpom data so we have everything in one place
teamstats <- read_csv('team_stats.csv', )
stats <- inner_join(teamstats, kp2, by = 'team')

# Like before, displays all our data in a clean, readable, datatable
data(stats, package='ggplot2')
datatable(stats, 
          extensions='Scroller',
          options = list(scrollX=TRUE))


Now, this is a fair amount of team statistics. Realistically we don’t need all of it to figure out our expected winners and losers. But, we’ll be taking a look at some of the stats we didn’t use later to figure out if something was missing from our predictions, and how we can better predict winners and losers in the future.

In addition to what we have already, we’re going to calculate a few more stats that we can use. The first of these is pppO and pppD, which are Points per Possession on both offense and defense, respectively. This is where the KenPom data begins to demonstrate how useful it is. The ORtg and DRtg statistics are opponent adjusted efficiencies for both points scored on offense and allowed on defense respectively, per-100 possessions. Therefore, we can divide those numbers by 100 to get our pppO and pppD.

# Gives us a per-possession alternative to offensive and defensive efficiency, rather 
# than per-100 possessions
stats1 <- stats |>
  mutate(pppO = ORtg / 100,
         pppD = DRtg / 100)


While in our expected points calculations we won’t be using these pppO and pppD figures themselves, opting to use the ORtg and DRtg instead, they might prove useful when we take a look at the “upsets” after creating our bracket simulation. We’re also going to create three more values that may prove useful later as well. These are:

  • epr (Effective Possession Ratio) - The number of shot opportunities a team has per possession.

  • ts (True Shooting) - Since basketball is scored in increments of 1, 2, and 3, ts tells us the points per shot opportunity that each team has. The constant 0.475 exists in the calculation for this number because only about 47.5% of Free Throws actually end a possession. Different sources have landed on different constants to use for this figure, but KenPom uses 0.475, so I’ve elected to stick with it as well.

  • ppp (Points Per Possession) - Even though we already have our opponent-adjusted pppO for each team, this figure gives us an objective estimate of each team’s opponent-independent scoring prowess. In basketball, teams have the same amount of possessions each game (+/- 1), so typically the team with the higher ppp wins. Using epr x ts to find ppp gives us a good estimate of each team’s scoring ability. It essentially tells us how often a team shoots, and how many points we expect out of each shot.

# Creates our epr, ts, and ppp variables for later use if needed
stats2 <- stats1 |>
  mutate(epr = ((poss.per.game + reb.off) - to.g) / poss.per.game,
         ts = scoring.off / (fga + (0.475 * fta.g)),
         ppp = epr * ts)


We’ll be creating a few more variables to look at once we start to dive into game outcomes, as well as matchup specific differences between teams. For now these numbers give us a solid framework of what each of the teams in the tournament brings to the table.

4 What Is A ‘Cinderella Story?’

In the next sections we’ll take a look at what actually happened in the 2025 March Madness tournament, along with what the model I mentioned earlier predicted would happen. Before that, however, I want to take a step back to elaborate on the title of this project. A “Cinderella Story” team in March Madness typically refers to an underdog, highly-seeded team that makes it much further in the tournament than anyone expects them to. We’ve already discussed which teams make the tournament, but the seeding process is relatively unknown outside of the room where the NCAA Committee makes their decisions. This is where our model deviates from the typical bracket-maker’s perception of each game. There are over 1,000 college basketball games played across the nation prior to March Madness, which is simply too many for any one person to watch all of them, including those on the committee. This is where they tend to get seeding “wrong”, as I alluded to earlier. While one school may technically be better than another on paper, they may not necessarily be favorites to win against a “lesser” opponent.

Due to this seeding, even before a single game has been played in the Round of 64 the Committee introduces a bias in favor of one team. If you hadn’t watched a college basketball game all season, you may expect a #7 or #2 seed to defeat a #10 seed with relative ease, but this year that wasn’t the case. For #10 Arkansas, they defied the odds in back to back games as a true Cinderella, not favored in either game by seeding or our model. This is the type of team we’re looking to identify before they bust our bracket. So, with that in mind, let’s look at the games. We’ll begin in the Round of 64.

5 The Model

Since all of the games have already been played, we can find the scores on the internet and make declarations about the outcome with the power of hindsight. But if we want to predict the outcome ahead of time, we’re going to need to use the data we found earlier to find opponent-adjusted expected values for each matchup. These equations are taken directly from the blog post mentioned earlier, with some variables adjusted to coincide with our data. We’ll start with tempo:

  • Using the AdjT values from our KenPom data, as well as the NCAA average that we calculated earlier, we can estimate the “tempo” of the game. This is a prediction for how many possessions each team will have per 40 minutes. Teams that play a lower-than-average tempo tend to control the pace of the game. They’re usually characterized by having low shot volume, but a high make percentage, favoring quality shots. Teams with a higher-than-average tempo are usually the opposite, favoring a high shot volume but lower make percentages. There’s not a “correct” way to play a game of basketball, but these different team identities is something we’ll investigate later. The expected tempo of a game played between Team A and Team B is:


Expected Tempo for Team A vs. B \[\begin{align*} E(Tempo_{A, B}) = \frac{AdjT_{A}}{AdjT_{NCAA}} * \frac{AdjT_{B}}{AdjT_{NCAA}} * AdjT_{NCAA} \end{align*}\]


  • We can use this expected tempo value to find our next important figure, Expected Field Goals Attempted. This will give us a measure of how many shots Team A is expected to take, opponent-adjusted for Team B’s defense. The equation we’ll use is:

Expected Field Goals Attempted by Team A vs. Team B \[\begin{align*} E(FGA_{A}) = FGA_{A} * \frac{E(Tempo_{A, B})}{AdjT_{A}} \end{align*}\]

  • Next, we’ll calculate the expected eFG% (Effective Field Goal Percentage). We haven’t explained eFG% yet, so what is it? eFG% is similar to a more common measure, FG%. FG% gives the percentage of field goals made per field goals attempted.* eFG% is slightly more nuanced than FG% because it accounts for both 2 and 3 point baskets. While I didn’t explicitly calculate the eFG% values in our dataset since they’re available in the TeamRankings data, the equation is given below.

*This is a good opportunity to mention that in basketball, a “field goal” is simply a shot from anywhere on the court during normal play, i.e. not a free throw. These are not the same as the field goals found in football.


Effective Field Goal Percentage (eFG%) \[\begin{align*} eFG\%\ = \frac{FG +(0.5*3P)}{FGA} \end{align*}\]

Expected eFG% for Team A vs. Team B \[\begin{align*} E(eFGO)_{A} = \frac{eFGO_{A}}{eFGO_{NCAA}} * \frac{eFGD_{B}}{eFGD_{NCAA}} * eFGO_{A} * \frac{1}{100} \end{align*}\]


  • Once we have both of those values, we’ll find the expected points scored by Team A against Team B. We do this by multiplying Team A’s adjusted efficiency on offense by Team B’s adjusted efficiency as well as the expected tempo of the game we calculated earlier, over the average NCAA defensive efficiency. Since our efficiencies ORtg and DRtg from the KenPom rankings are given as points scored/allowed per-100 possessions by nature, we end up with the expected points for each team.


Expected Points for Team A vs. Team B \[\begin{align*} E(Points)_{A} = \frac{ORtg_{A} * DRtg_{B} * E(Tempo_{A,B})}{DRtg_{NCAA}} * \frac{1}{100} \end{align*}\]


In my initial foray into this binomial distribution approach, this was the point where I stopped. Unaware of how to effectively model the distribution using the variance we’ll look at next, I deemed the expected score sufficient; and to some extent it was. In 56/67 games the team who was expected to score more points using this method, did. But this time around we’ll look at the variance in order to add win probabilities to our predictions.


  • To calculate the variance in scoring for Team A we’ll use the formula below. If we view field goals attempted as trials, and our eFG% as the probability of success, we can easily find the variance for our distribution.

Expected Variance in Scoring for Team A vs. Team B \[\begin{align*} Var(Points_{A}) = E(FGA_{A}) * E(eFGO_{A})(1-eFGO_{A}) * 2 \end{align*}\]


Now that we have all the equations we’ll need, we can begin to start putting together our bracket.


6 Building the Bracket

To remain within the scope of this project, I’ll refrain from building an entire bracket simulation. Instead, opting to go game by game and manually enter the matchups for each. But in order to do that in a reasonable amount of time, we’re going to need to put together some functions using the equations we just described and the averages we calculated earlier.

# Expected Tempo for Team A vs. B
etempo <- function(teama, teamb){
  (stats2[stats2$team == teama, "AdjT"] / AdjTncaa) * (stats2[stats2$team == teamb, "AdjT"] / AdjTncaa) * AdjTncaa
}

# Expected Field Goals Attempted by Team A vs. Team B
efgaa <- function(teama, teamb){
  stats2[stats2$team == teama, "fga"] * (etempo(teama, teamb) / stats2[stats2$team == teama, "AdjT"])
}

# Expected Field Goals Attempted by Team B vs. Team A
efgab <- function(teama, teamb){
  stats2[stats2$team == teamb, "fga"] * (etempo(teama, teamb) / stats2[stats2$team == teamb, "AdjT"])
}

# Expected eFG% for Team A vs. Team B
eefgoa <- function(teama, teamb){
  (stats2[stats2$team == teama, "eFG"] / eFGOncaa) * (stats2[stats2$team == teamb, "opp.eFG"] / eFGDncaa) * stats2[stats2$team == teama, "eFG"]
}

# Expected eFG% for Team B vs. Team A
eefgob <- function(teama, teamb){
  (stats2[stats2$team == teamb, "eFG"] / eFGOncaa) * (stats2[stats2$team == teama, "opp.eFG"] / eFGDncaa) * stats2[stats2$team == teamb, "eFG"]
}

# Expected Points for Team A vs. Team B
epointsa <- function(teama, teamb){
  ((stats2[stats2$team == teama, "ORtg"] * stats2[stats2$team == teamb, "DRtg"] * etempo(teama, teamb)) / DRtgncaa) * (1/100)
}

# Expected Points for Team B vs. Team A
epointsb <- function(teama, teamb){
  ((stats2[stats2$team == teamb, "ORtg"] * stats2[stats2$team == teama, "DRtg"] * etempo(teama, teamb)) / DRtgncaa) * (1/100)
}

# Expected Variance in Scoring for Team A vs. Team B, converted to a numeric value to avoid issues with the 
# 'matchup' function introduced next
varpointsa <- function(teama, teamb){
  vara <- efgaa(teama, teamb) * (eefgoa(teama, teamb)*(1 - eefgoa(teama, teamb))) * 2
  va <- as.numeric(vara)
  return(va)
}

# Expected Variance in Scoring for Team B vs. Team A
varpointsb <- function(teama, teamb){
  varb <- efgab(teama, teamb) * (eefgob(teama, teamb)*(1 - eefgob(teama, teamb))) * 2
  vb <- as.numeric(varb)
  return(vb)
}


# This function takes the scores that we just found for Team A and Team B, and concatenates them using the "glue" package.
# We can use this function to now run through the entire tournament round by round. 
matchup <- function(teama, teamb){
  pa <- round(epointsa(teama, teamb), digits = 2)
  pb <- round(epointsb(teama, teamb), digits = 2)
  
  va <- varpointsa(teama, teamb)
  vb <- varpointsb(teama, teamb)
  
  # Since we know the expected score and the variance, we can use those to find win probabilities for each team
  z <- (pa - pb) / sqrt(va + vb)
  z <- as.numeric(z)
  
  # Using our z score, find win percentage a and b
  wpa <- round(pnorm(z), digits = 3)
  wpb <- round(1 - pnorm(z), digits = 3)
  
  # Declares the winner based on the higher win probability
  if (wpa > wpb){
    win <- teama
  } else{
    win <- teamb
  }
  
  # Calculates the expected point differential
  if (pa > pb){
    pd <- round(pa - pb, digits = 2)
  } else{
    pd <- round(pb-pa, digits = 2)
  }
  
  # Uses the "glue" package to put all of our results together into a nice output and prints it afterwards.
  out <- glue("{teama} Expected score: {pa}, 
              {teamb} Expected score: {pb},
              Projected Point Differential: {pd}
              Win Probability for {teama}: {wpa}
              Win Probability for {teamb}: {wpb}
              Projected winner: {win}")
  
  out
}


Now that we have our functions, we can easily run through each matchup and reduce 67 basketball games to a few function calls.

Our Predictions

Round of 64

The South Region

matchup("Auburn", "Alabama St.")
## Auburn Expected score: 90.66, 
## Alabama St. Expected score: 60.35,
## Projected Point Differential: 30.31
## Win Probability for Auburn: 1
## Win Probability for Alabama St.: 0
## Projected winner: Auburn
matchup("Louisville", "Creighton")
## Louisville Expected score: 74.52, 
## Creighton Expected score: 71.66,
## Projected Point Differential: 2.86
## Win Probability for Louisville: 0.647
## Win Probability for Creighton: 0.353
## Projected winner: Louisville
matchup("Michigan", "UC San Diego")
## Michigan Expected score: 71.22, 
## UC San Diego Expected score: 68.49,
## Projected Point Differential: 2.73
## Win Probability for Michigan: 0.641
## Win Probability for UC San Diego: 0.359
## Projected winner: Michigan
matchup("Texas A&M", "Yale")
## Texas A&M Expected score: 74.9, 
## Yale Expected score: 65.64,
## Projected Point Differential: 9.26
## Win Probability for Texas A&M: 0.886
## Win Probability for Yale: 0.114
## Projected winner: Texas A&M
matchup("Ole Miss", "North Carolina")
## Ole Miss Expected score: 78.16, 
## North Carolina Expected score: 76.61,
## Projected Point Differential: 1.55
## Win Probability for Ole Miss: 0.578
## Win Probability for North Carolina: 0.422
## Projected winner: Ole Miss
matchup("Iowa St.", "Lipscomb")
## Iowa St. Expected score: 77.65, 
## Lipscomb Expected score: 65.62,
## Projected Point Differential: 12.03
## Win Probability for Iowa St.: 0.946
## Win Probability for Lipscomb: 0.054
## Projected winner: Iowa St.
matchup("Marquette", "New Mexico")
## Marquette Expected score: 76.78, 
## New Mexico Expected score: 73.93,
## Projected Point Differential: 2.85
## Win Probability for Marquette: 0.638
## Win Probability for New Mexico: 0.362
## Projected winner: Marquette
matchup("Michigan St.", "Bryant")
## Michigan St. Expected score: 85.4, 
## Bryant Expected score: 66.07,
## Projected Point Differential: 19.33
## Win Probability for Michigan St.: 0.992
## Win Probability for Bryant: 0.008
## Projected winner: Michigan St.

The West Region

matchup("Florida", "Norfolk St.")
## Florida Expected score: 89.92, 
## Norfolk St. Expected score: 63.71,
## Projected Point Differential: 26.21
## Win Probability for Florida: 1
## Win Probability for Norfolk St.: 0
## Projected winner: Florida
matchup("UConn", "Oklahoma")
## UConn Expected score: 74.66, 
## Oklahoma Expected score: 74.32,
## Projected Point Differential: 0.34
## Win Probability for UConn: 0.518
## Win Probability for Oklahoma: 0.482
## Projected winner: UConn
matchup("Memphis", "Colorado St.")
## Memphis Expected score: 73.01, 
## Colorado St. Expected score: 73.82,
## Projected Point Differential: 0.81
## Win Probability for Memphis: 0.457
## Win Probability for Colorado St.: 0.543
## Projected winner: Colorado St.
matchup("Maryland", "Grand Canyon")
## Maryland Expected score: 82.54, 
## Grand Canyon Expected score: 68.75,
## Projected Point Differential: 13.79
## Win Probability for Maryland: 0.959
## Win Probability for Grand Canyon: 0.041
## Projected winner: Maryland
matchup("Missouri", "Drake")
## Missouri Expected score: 68.99, 
## Drake Expected score: 63.45,
## Projected Point Differential: 5.54
## Win Probability for Missouri: 0.788
## Win Probability for Drake: 0.212
## Projected winner: Missouri
matchup("Texas Tech", "UNCW")
## Texas Tech Expected score: 79.89, 
## UNCW Expected score: 64.98,
## Projected Point Differential: 14.91
## Win Probability for Texas Tech: 0.977
## Win Probability for UNCW: 0.023
## Projected winner: Texas Tech
matchup("Kansas", "Arkansas")
## Kansas Expected score: 72.97, 
## Arkansas Expected score: 69.21,
## Projected Point Differential: 3.76
## Win Probability for Kansas: 0.684
## Win Probability for Arkansas: 0.316
## Projected winner: Kansas
matchup("St. John's (NY)", "Omaha")
## St. John's (NY) Expected score: 83.34, 
## Omaha Expected score: 64.32,
## Projected Point Differential: 19.02
## Win Probability for St. John's (NY): 0.992
## Win Probability for Omaha: 0.008
## Projected winner: St. John's (NY)

The East Region

matchup("Duke", "Mount St. Mary's")
## Duke Expected score: 84.46, 
## Mount St. Mary's Expected score: 55.42,
## Projected Point Differential: 29.04
## Win Probability for Duke: 1
## Win Probability for Mount St. Mary's: 0
## Projected winner: Duke
matchup("Mississippi St.", "Baylor")
## Mississippi St. Expected score: 72.52, 
## Baylor Expected score: 72.93,
## Projected Point Differential: 0.41
## Win Probability for Mississippi St.: 0.479
## Win Probability for Baylor: 0.521
## Projected winner: Baylor
matchup("Oregon", "Liberty")
## Oregon Expected score: 70.89, 
## Liberty Expected score: 66.86,
## Projected Point Differential: 4.03
## Win Probability for Oregon: 0.71
## Win Probability for Liberty: 0.29
## Projected winner: Oregon
matchup("Arizona", "Akron")
## Arizona Expected score: 91.26, 
## Akron Expected score: 76.7,
## Projected Point Differential: 14.56
## Win Probability for Arizona: 0.965
## Win Probability for Akron: 0.035
## Projected winner: Arizona
matchup("BYU", "VCU")
## BYU Expected score: 73.04, 
## VCU Expected score: 72.32,
## Projected Point Differential: 0.72
## Win Probability for BYU: 0.538
## Win Probability for VCU: 0.462
## Projected winner: BYU
matchup("Wisconsin", "Montana")
## Wisconsin Expected score: 85.11, 
## Montana Expected score: 67.09,
## Projected Point Differential: 18.02
## Win Probability for Wisconsin: 0.993
## Win Probability for Montana: 0.007
## Projected winner: Wisconsin
matchup("Saint Mary's (CA)", "Vanderbilt")
## Saint Mary's (CA) Expected score: 70.16, 
## Vanderbilt Expected score: 65.03,
## Projected Point Differential: 5.13
## Win Probability for Saint Mary's (CA): 0.748
## Win Probability for Vanderbilt: 0.252
## Projected winner: Saint Mary's (CA)
matchup("Alabama", "Robert Morris")
## Alabama Expected score: 93.81, 
## Robert Morris Expected score: 72.99,
## Projected Point Differential: 20.82
## Win Probability for Alabama: 0.996
## Win Probability for Robert Morris: 0.004
## Projected winner: Alabama

The Midwest Region

matchup("Houston", "SIU Edwardsville")
## Houston Expected score: 73.68, 
## SIU Edwardsville Expected score: 50.39,
## Projected Point Differential: 23.29
## Win Probability for Houston: 0.999
## Win Probability for SIU Edwardsville: 0.001
## Projected winner: Houston
matchup("Gonzaga", "Georgia")
## Gonzaga Expected score: 77.03, 
## Georgia Expected score: 72.21,
## Projected Point Differential: 4.82
## Win Probability for Gonzaga: 0.732
## Win Probability for Georgia: 0.268
## Projected winner: Gonzaga
matchup("Clemson", "McNeese")
## Clemson Expected score: 69.93, 
## McNeese Expected score: 63.45,
## Projected Point Differential: 6.48
## Win Probability for Clemson: 0.808
## Win Probability for McNeese: 0.192
## Projected winner: Clemson
matchup("Purdue", "High Point")
## Purdue Expected score: 81.59, 
## High Point Expected score: 71.58,
## Projected Point Differential: 10.01
## Win Probability for Purdue: 0.917
## Win Probability for High Point: 0.083
## Projected winner: Purdue
matchup("Illinois", "Xavier")
## Illinois Expected score: 82.16, 
## Xavier Expected score: 77.81,
## Projected Point Differential: 4.35
## Win Probability for Illinois: 0.709
## Win Probability for Xavier: 0.291
## Projected winner: Illinois
matchup("Kentucky", "Troy")
## Kentucky Expected score: 81.61, 
## Troy Expected score: 70.28,
## Projected Point Differential: 11.33
## Win Probability for Kentucky: 0.929
## Win Probability for Troy: 0.071
## Projected winner: Kentucky
matchup("UCLA", "Utah St.")
## UCLA Expected score: 75.45, 
## Utah St. Expected score: 70.04,
## Projected Point Differential: 5.41
## Win Probability for UCLA: 0.768
## Win Probability for Utah St.: 0.232
## Projected winner: UCLA
matchup("Tennessee", "Wofford")
## Tennessee Expected score: 74.67, 
## Wofford Expected score: 57.48,
## Projected Point Differential: 17.19
## Win Probability for Tennessee: 0.99
## Win Probability for Wofford: 0.01
## Projected winner: Tennessee

Results

So, how did we do? Not good enough, if 67/67 is our eventual goal. But let’s take a look at what games we got wrong and keep a running tally in the Results tab so that we can take a look at those teams afterwards.

The games we got wrong and their respective Win Probabilities:

  • #8 Louisville (64.7%) vs #9 Creighton (35.3%)

  • #7 Marquette (63.8%) vs #10 New Mexico (36.2%)

  • #6 Missouri (78.8%) vs #11 Drake (21.2%)

  • #7 Kansas (68.4%) vs #10 Arkansas (31.6%)

  • #5 Clemson (80.8%) vs #12 McNeese (19.2%)

Round of 32

The South Region

matchup("Auburn", "Creighton")
## Auburn Expected score: 79.67, 
## Creighton Expected score: 68.86,
## Projected Point Differential: 10.81
## Win Probability for Auburn: 0.921
## Win Probability for Creighton: 0.079
## Projected winner: Auburn
matchup("Michigan", "Texas A&M")
## Michigan Expected score: 68.32, 
## Texas A&M Expected score: 69.62,
## Projected Point Differential: 1.3
## Win Probability for Michigan: 0.432
## Win Probability for Texas A&M: 0.568
## Projected winner: Texas A&M
matchup("Ole Miss", "Iowa St.")
## Ole Miss Expected score: 70.84, 
## Iowa St. Expected score: 74.3,
## Projected Point Differential: 3.46
## Win Probability for Ole Miss: 0.327
## Win Probability for Iowa St.: 0.673
## Projected winner: Iowa St.
matchup("New Mexico", "Michigan St.")
## New Mexico Expected score: 69.73, 
## Michigan St. Expected score: 77.28,
## Projected Point Differential: 7.55
## Win Probability for New Mexico: 0.172
## Win Probability for Michigan St.: 0.828
## Projected winner: Michigan St.

The West Region

matchup("Florida", "UConn")
## Florida Expected score: 81.54, 
## UConn Expected score: 69.61,
## Projected Point Differential: 11.93
## Win Probability for Florida: 0.94
## Win Probability for UConn: 0.06
## Projected winner: Florida
matchup("Colorado St.", "Maryland")
## Colorado St. Expected score: 68.38, 
## Maryland Expected score: 75.16,
## Projected Point Differential: 6.78
## Win Probability for Colorado St.: 0.187
## Win Probability for Maryland: 0.813
## Projected winner: Maryland
matchup("Drake", "Texas Tech")
## Drake Expected score: 58.67, 
## Texas Tech Expected score: 66.16,
## Projected Point Differential: 7.49
## Win Probability for Drake: 0.142
## Win Probability for Texas Tech: 0.858
## Projected winner: Texas Tech
matchup("Arkansas", "St. John's (NY)")
## Arkansas Expected score: 67.03, 
## St. John's (NY) Expected score: 73.43,
## Projected Point Differential: 6.4
## Win Probability for Arkansas: 0.212
## Win Probability for St. John's (NY): 0.788
## Projected winner: St. John's (NY)

The East Region

matchup("Duke", "Baylor")
## Duke Expected score: 75.38, 
## Baylor Expected score: 64.01,
## Projected Point Differential: 11.37
## Win Probability for Duke: 0.938
## Win Probability for Baylor: 0.062
## Projected winner: Duke
matchup("Oregon", "Arizona")
## Oregon Expected score: 74.34, 
## Arizona Expected score: 77.93,
## Projected Point Differential: 3.59
## Win Probability for Oregon: 0.323
## Win Probability for Arizona: 0.677
## Projected winner: Arizona
matchup("BYU", "Wisconsin")
## BYU Expected score: 74.77, 
## Wisconsin Expected score: 77.72,
## Projected Point Differential: 2.95
## Win Probability for BYU: 0.349
## Win Probability for Wisconsin: 0.651
## Projected winner: Wisconsin
matchup("Saint Mary's (CA)", "Alabama")
## Saint Mary's (CA) Expected score: 71.58, 
## Alabama Expected score: 75.03,
## Projected Point Differential: 3.45
## Win Probability for Saint Mary's (CA): 0.331
## Win Probability for Alabama: 0.669
## Projected winner: Alabama

The Midwest Region

matchup("Houston", "Gonzaga")
## Houston Expected score: 71.28, 
## Gonzaga Expected score: 65.15,
## Projected Point Differential: 6.13
## Win Probability for Houston: 0.786
## Win Probability for Gonzaga: 0.214
## Projected winner: Houston
matchup("McNeese", "Purdue")
## McNeese Expected score: 68, 
## Purdue Expected score: 74.02,
## Projected Point Differential: 6.02
## Win Probability for McNeese: 0.205
## Win Probability for Purdue: 0.795
## Projected winner: Purdue
matchup("Illinois", "Kentucky")
## Illinois Expected score: 85.33, 
## Kentucky Expected score: 85.58,
## Projected Point Differential: 0.25
## Win Probability for Illinois: 0.488
## Win Probability for Kentucky: 0.512
## Projected winner: Kentucky
matchup("UCLA", "Tennessee")
## UCLA Expected score: 59.93, 
## Tennessee Expected score: 65.83,
## Projected Point Differential: 5.9
## Win Probability for UCLA: 0.212
## Win Probability for Tennessee: 0.788
## Projected winner: Tennessee

Results

The games we got wrong and their respective Win Probabilities:

  • #5 Michigan (43.2%) vs #4 Texas A&M (56.8%)

  • #6 Ole Miss (32.7%) vs #3 Iowa St. (67.3%)

  • #10 Arkansas (21.2%) vs #2 St. John’s (78.8%)

  • #6 BYU (34.9%) vs #3 Wisconsin (65.1%)

Sweet Sixteen

The South Region

matchup("Auburn", "Michigan")
## Auburn Expected score: 78.74, 
## Michigan Expected score: 70.78,
## Projected Point Differential: 7.96
## Win Probability for Auburn: 0.847
## Win Probability for Michigan: 0.153
## Projected winner: Auburn
matchup("Ole Miss", "Michigan St.")
## Ole Miss Expected score: 68.47, 
## Michigan St. Expected score: 72.59,
## Projected Point Differential: 4.12
## Win Probability for Ole Miss: 0.298
## Win Probability for Michigan St.: 0.702
## Projected winner: Michigan St.

The West Region

matchup("Florida", "Maryland")
## Florida Expected score: 79.95, 
## Maryland Expected score: 73.9,
## Projected Point Differential: 6.05
## Win Probability for Florida: 0.774
## Win Probability for Maryland: 0.226
## Projected winner: Florida
matchup("Texas Tech", "Arkansas")
## Texas Tech Expected score: 75.36, 
## Arkansas Expected score: 69.39,
## Projected Point Differential: 5.97
## Win Probability for Texas Tech: 0.782
## Win Probability for Arkansas: 0.218
## Projected winner: Texas Tech

The East Region

matchup("Duke", "Arizona")
## Duke Expected score: 79.32, 
## Arizona Expected score: 70.4,
## Projected Point Differential: 8.92
## Win Probability for Duke: 0.878
## Win Probability for Arizona: 0.122
## Projected winner: Duke
matchup("BYU", "Alabama")
## BYU Expected score: 83.17, 
## Alabama Expected score: 89.17,
## Projected Point Differential: 6
## Win Probability for BYU: 0.223
## Win Probability for Alabama: 0.777
## Projected winner: Alabama

The Midwest Region

matchup("Houston", "Purdue")
## Houston Expected score: 68.81, 
## Purdue Expected score: 60.71,
## Projected Point Differential: 8.1
## Win Probability for Houston: 0.866
## Win Probability for Purdue: 0.134
## Projected winner: Houston
matchup("Kentucky", "Tennessee")
## Kentucky Expected score: 69.33, 
## Tennessee Expected score: 75.24,
## Projected Point Differential: 5.91
## Win Probability for Kentucky: 0.22
## Win Probability for Tennessee: 0.78
## Projected winner: Tennessee

Results

The games we got wrong and their respective Win Probabilities:

  • None

Elite Eight

The South Region

matchup("Auburn", "Michigan St.")
## Auburn Expected score: 74.19, 
## Michigan St. Expected score: 70.35,
## Projected Point Differential: 3.84
## Win Probability for Auburn: 0.689
## Win Probability for Michigan St.: 0.311
## Projected winner: Auburn

The West Region

matchup("Florida", "Texas Tech")
## Florida Expected score: 79.31, 
## Texas Tech Expected score: 73.46,
## Projected Point Differential: 5.85
## Win Probability for Florida: 0.772
## Win Probability for Texas Tech: 0.228
## Projected winner: Florida

The East Region

matchup("Duke", "Alabama")
## Duke Expected score: 84.62, 
## Alabama Expected score: 77.73,
## Projected Point Differential: 6.89
## Win Probability for Duke: 0.808
## Win Probability for Alabama: 0.192
## Projected winner: Duke

The Midwest Region

matchup("Houston", "Tennessee")
## Houston Expected score: 59.75, 
## Tennessee Expected score: 57.49,
## Projected Point Differential: 2.26
## Win Probability for Houston: 0.621
## Win Probability for Tennessee: 0.379
## Projected winner: Houston

Results

The games we got wrong and their respective Win Probabilities:

  • None

Final Four

South/West

matchup("Auburn", "Florida")
## Auburn Expected score: 77.87, 
## Florida Expected score: 78.69,
## Projected Point Differential: 0.82
## Win Probability for Auburn: 0.459
## Win Probability for Florida: 0.541
## Projected winner: Florida

East/Midwest

matchup("Duke", "Houston")
## Duke Expected score: 63.19, 
## Houston Expected score: 62.14,
## Projected Point Differential: 1.05
## Win Probability for Duke: 0.556
## Win Probability for Houston: 0.444
## Projected winner: Duke

Results

The game we got wrong and its respective Win Probability:

  • #1 Duke (55.6%) vs #1 Houston (44.4%)

National Championship

You may have noticed by now that each round, I am replacing the results that we predicted with the real-life outcomes. Up to this point it wouldn’t have made a difference outside of one game, #10 Arkansas vs #2 St. John’s. Every other team we incorrectly guessed would lose, besides Arkansas, went on to lose in the next round and didn’t change the outcome of the Sweet Sixteen and Elite Eight. Houston, ironically, is not an exception to this rule, despite our prediction giving them a slight edge in this final, incorrect, result. In reality, Florida defeated Houston 65-63 to claim the National Title.

If this were next year’s bracket and we didn’t know all of the outcomes yet, incorrectly guessing the winner of both a Final Four game and the Championship would be an incredibly poor way to lose a perfect bracket. But this highlights a concept that I’ll touch on later despite not fully understanding. As the field narrows and the level of play increases, our predictions, in theory, should be worse.

matchup("Florida", "Houston")
## Florida Expected score: 67.26, 
## Houston Expected score: 67.81,
## Projected Point Differential: 0.55
## Win Probability for Florida: 0.472
## Win Probability for Houston: 0.528
## Projected winner: Houston

The game we got wrong and its respective Win Probability:

  • #1 Florida (47.2%) vs #1 Houston (52.8%)

7 The Results

Before we get into graphing these teams and trying to come up with some clues that may have prevented our bracket from busting on the very first game of the Round of 64 (Louisville vs Creighton), let’s just take a look at all of the matchups we got incorrectly in one place. Of my 56/67 results, here are all 11 incorrect predictions.

Round of 64

  • #8 Louisville (64.7%) vs #9 Creighton (35.3%)

  • #7 Marquette (63.8%) vs #10 New Mexico (36.2%)

  • #6 Missouri (78.8%) vs #11 Drake (21.2%)

  • #7 Kansas (68.4%) vs #10 Arkansas (31.6%)

  • #5 Clemson (80.8%) vs #12 McNeese (19.2%)

Round of 32

  • #5 Michigan (43.2%) vs #4 Texas A&M (56.8%)

  • #6 Ole Miss (32.7%) vs #3 Iowa St. (67.3%)

  • #10 Arkansas (21.2%) vs #2 St. John’s (78.8%)

  • #6 BYU (34.9%) vs #3 Wisconsin (65.1%)

Final Four

  • #1 Duke (55.6%) vs #1 Houston (44.4%)

National Championship

  • #1 Florida (47.2%) vs #1 Houston (52.8%)


We can see that as we get closer to the Championship, and then in the Championship itself, the level of competition gets much more even. Our win probabilities amount to essentially a coin flip, especially when considering that the scores of each game after the Elite Eight is predicted to be within 1 point. None of the games actually ended in such a narrow margin, but both of the games that we predicted incorrectly were decided by one possession. The only game we got correct (Auburn vs Florida) was decided by 6 points, or just two possessions.

Getting all of the Sweet Sixteen and Elite Eight games correct as the competition narrows is a result I’m content with, but doesn’t serve us too much useful information. In fact, out of all twelve games played in those rounds that we got correct, only three of them ended within one possession. Realistically, there’s an element of luck when it comes to deciding which team will win these coin flip games if we go strictly by the score predictions, and not some other metric.

On the other end of the spectrum, are the true upsets - the beginnings of a Cinderella Story. While 2025’s bracket featured relatively little chaos, there are two teams that stand out from the crowd in our group of incorrect predictions above. The first, who has been mentioned on more than one occasion already, the Arkansas Razorbacks. The only double-digit seed to make it to the Sweet Sixteen with relatively modest, but respectable stats, the Razorbacks weren’t necessarily a prototypical Cinderella team. By virtue of playing in the SEC, which many considered to be the strongest conference in the nation last year, they carried a lot more talent than their seeding might suggest. However, we were still unable to predict either of their upset wins correctly.

The other notable team, owners of the largest upset victory throughout the entire tournament - the McNeese Cowboys. This result hits particularly close to home, as it came at the consequence of an early exit for my own Clemson Tigers. I will refrain from making any biased comments or assumptions about the outcome of that game that can’t be verified by the data I have in front of me, and will instead opt to credit the unexpected loss to an injury suffered by Clemson guard Dillon Hunter during the ACC Tournament.

The rest of the incorrect guesses tend to fall in the range of around a 30-45% win probability percentage for the underdogs. These are results that likely could have gone either way, but without investigating them further we’re left victims of chance. In order to try and garner some insight, I’ll explore some of the statistics we have at our disposal to see if there’s a discrepancy between our “Cinderellas” and our proverbial “stepsisters.”

8 The Glass Slipper - What Sets Teams Apart?

We’ll first start by creating a subset of the teams that pulled off an “upset” given our predictions, and a separate subset of the teams who lost to them. That way, we can highlight each and see if there’s any significant differences between the two groups.


# Filters out just our "underdogs"
unders <- stats2 |>
  filter(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))

# Filters out just the teams our "underdogs" lost to
upsets <- stats2 |>
  filter(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))

ggplot(stats2, aes(x = eFG, y = opp.eFG))+
  geom_vline(xintercept = mean(stats2$eFG), color = "black")+
  geom_hline(yintercept = mean(stats2$opp.eFG), color = "black")+
  geom_cbb_teams(data = stats2, aes(team = team), width = 0.05, show.legend = FALSE)+
  gghighlight(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))+
  xlim(min(stats2$eFG), max(stats2$eFG))+
  ylim(min(stats2$opp.eFG), max(stats2$opp.eFG))+
  labs(x = "Team eFG%",
       y = "Opponent eFG%",
       title = 'Team eFG% vs. Opponent eFG% for "Underdog" Teams')

ggplot(stats2, aes(x = eFG, y = opp.eFG))+
  geom_vline(xintercept = mean(stats2$eFG), color = "black")+
  geom_hline(yintercept = mean(stats2$opp.eFG), color = "black")+
  geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
  gghighlight(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))+
  xlim(min(stats2$eFG), max(stats2$eFG))+
  ylim(min(stats2$opp.eFG), max(stats2$opp.eFG))+
  labs(x = "Team eFG%",
       y = "Opponent eFG%",
       title = 'Team eFG% vs. Opponent eFG% for Teams Who Were "Upset"')


Here we get some slight insight as to the difference between a few of these teams, but for the most part the results are inconclusive. In this particular graph, you want to be in the bottom right quadrant with a high eFG%, and a low opp.eFG%. We can see that teams like McNeese, Creighton, and Michigan fare better in both eFG% and opp.eFG% than their opponents, but more often than not the pattern doesn’t seem to hold. It’s still worth noting that six of the teams who suffered upset losses had a below average eFG%, and Clemson is just sightly above average.


Since eFG% and opp.eFG% aren’t opponent-adjusted, we can try to compare our opponent-adjusted efficiencies and see if that gives us some more insight. Even though this follows our methodology for finding our expected scores, and likely won’t tell us much, one or two outliers could be the difference maker when deciding which otherwise evenly-matched team we should pick.

ggplot(stats2, aes(x = ORtg, y = DRtg))+
  geom_vline(xintercept = mean(stats2$ORtg), color = "black")+
  geom_hline(yintercept = mean(stats2$DRtg), color = "black")+
  geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
  gghighlight(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))+
  xlim(min(stats2$ORtg), max(stats2$ORtg))+
  ylim(min(stats2$DRtg), max(stats2$DRtg))+
  labs(x = "Team ORtg",
       y = "Team DRtg",
       title = 'Team ORtg vs. Team DRtg for "Underdog" Teams')

ggplot(stats2, aes(x = ORtg, y = DRtg))+
  geom_vline(xintercept = mean(stats2$ORtg), color = "black")+
  geom_hline(yintercept = mean(stats2$DRtg), color = "black")+
  geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
  gghighlight(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))+
  xlim(min(stats2$ORtg), max(stats2$ORtg))+
  ylim(min(stats2$DRtg), max(stats2$DRtg))+
  labs(x = "Team ORtg",
       y = "Team DRtg",
       title = 'Team ORtg vs. Team DRtg for Teams Who Were "Upset"')


As expected, this graph doesn’t tell us all too much either. The only real insight here might be that given the clustering of the teams who faced upsets, the ones who lost in the Round of 64 and Round of 32 don’t do anything exceptionally well. They’re above average in offensive and defensive efficiency, but they aren’t immune to losing a basketball game. The other teams all the way out on the right end of the graph with Duke in ORtg are Florida, who would eventually go on to win the Tournament, and Auburn, who lost to Florida in the Final Four.

The team closest to Houston on this graph? Tennessee. Who they defeated in the Elite Eight. I think it’s not unreasonable to say that these teams are somewhat immune to upsets, all the way down in the bottom right of the graph. Teams like St. John’s and Missouri though, who excel on one end of the court and are relatively pedestrian on the other, don’t share that luxury.


We’ve determined that scoring efficiency matters to some extent, as does the amount each team scores per shot. Let’s take those concepts now, and look to see if these teams fit into either of the “team identities” we mentioned earlier. Across the sport of basketball, the three-pointer has completely reshaped the scoring landscape. Perhaps we can see if there’s a discrepancy between the slower, more methodical teams who try to craft the perfect shot, and the more “run and gun” style of play.

ggplot(stats2, aes(x = AdjT, y = threep.perc.off))+
  geom_vline(xintercept = mean(stats2$AdjT), color = "black")+
  geom_hline(yintercept = mean(stats2$threep.perc.off), color = "black")+
  geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
  gghighlight(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))+
  xlim(min(stats2$AdjT), max(stats2$AdjT))+
  ylim(min(stats2$threep.perc.off), max(stats2$threep.perc.off))+
  labs(x = "Team AdjT",
       y = "Team 3P%",
       title = 'Team AdjT vs. Team 3P% for "Underdog" Teams')

ggplot(stats2, aes(x = AdjT, y = threep.perc.off))+
  geom_vline(xintercept = mean(stats2$AdjT), color = "black")+
  geom_hline(yintercept = mean(stats2$threep.perc.off), color = "black")+
  geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
  gghighlight(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))+
  xlim(min(stats2$AdjT), max(stats2$AdjT))+
  ylim(min(stats2$threep.perc.off), max(stats2$threep.perc.off))+
  labs(x = "Team AdjT",
       y = "Team 3P%",
       title = 'Team AdjT vs. Team 3P% for Teams Who Were "Upset"')


Right off the bat, this graph gives us an excellent look at a couple matchup-specific differences between teams. We can see a few clear trends right away, that seem to hold with our earlier assumptions. The first of these is that high-tempo teams struggle against low tempo teams. This was a concept I generally grasped and had brought up already, but now we can see clearly just how big of an impact it can have. #11 Drake plays at an absolutely glacial pace, averaging just 58.8 possessions per game. They’re the slowest team in the country, and that change of pace was enough for them to topple a fast Missouri team who couldn’t adjust to essentially walking up and down the court. Unfortunately for Drake, they ran into Texas Tech in the Round of 32 (the point on the graph right above Duke). Texas Tech is comfortable playing at a slower than average tempo, and shoots much more efficiently than Drake, at a higher volume. For teams that play at a similar tempo, within 2-3 possessions per game, the more efficient teams almost always win.

There are only three exceptions to this rule in our plot, one of which we already deemed a coin flip earlier in #1 Houston vs #1 Florida. Coincidentally, those two exceptions are our “Cinderella” teams. Or so it may seem. Along with Clemson, who was without Dillon Hunter in their first and only game in the tournament, Kansas was also playing shorthanded. Briefly. Leading 67-64 over Arkansas with 3:10 on the clock, Jayhawks’ star forward KJ Adams tore his achilles and was forced to leave the game. In the remaining 3 minutes and 10 seconds Arkansas would go on to outscore Kansas 15-5, closing out the game with a final score of 79-72 in favor of the Razorbacks. Outside of those two injury-related anomalies, and the National Championship game, our rule holds across all the other upsets. When two otherwise evenly-matched teams square off against each other, the team that’s more efficient from behind the arc is almost always going to win.

You can investigate all of this for yourself using the flexdashboard I’ve created for this data as well.

9 Takeaways

Our win probabilities give us a good idea of clear winners. Any team with a 70% chance to win or better won in all but three instances. Two of these we can attribute to injuries adding an element of randomness, and the third we can attribute to a vast difference between the two teams’ shooting ability, which is just part of the Rick Pitino Experience. Any team with a 30% chance to win or better, can win. We can almost perfectly predict the outcome in these games based on two things. The first is tempo, much slower teams hold an advantage over teams that like to play faster than average. The second, when tempo is not a question, is 3P%. Teams that are able to score threes at a higher clip than their opponent almost always walk away with a victory over less-efficient shooting. Our notable exception to this is the National Championship game, where the best offense in the country faced off against the (second) best defense in the country. These teams at the very top of our offensive and defensive rankings seem to be juggernauts when moving through bracket, and until they meet an opponent with similar ability, they’re going to easily make their way towards the later rounds.

It’s impossible to predict injuries. No model can account for that event in the middle of the tournament. But that’s the beauty of solving the March Madness bracket. Simply put, nobody knows what’s going to happen and there’s an element of randomness that comes with making picks. Some may even call it luck. I posit that if we were to look at every individual matchup and apply only the rules comparing 3P% to AdjT in cases where closely matched teams play at a similar speed, and favoring the slower team if they don’t, our bracket would put up some reasonably successful results.

Regardless of the inherent randomness that comes with any live sporting event, we can definitely draw a lot more insights from this approach than I began with. By applying this concept of “team identities,” rather than blindly following a score prediction, I wouldn’t be surprised if this model, when applied with a new, deeper understanding of team matchups, sees upwards of 60/67 correct picks.

There’s 40 different variables - some more important than others - in this dataset. I could sit here for the next few months of my life investigating each, building a regression model with all 40 and trying to fit it perfectly. At the end of the day, nothing’s going to account for the randomness. In fact, among my friend group, despite being correct on 56/67 picks compared to our winner who achieved a solid 51/67, if I had used only the score predictions of this particular model I would’ve come in just sixth place out of the sixteen of us in our “bracket pool.” There, the scoring favors the Final Four and Championship much more heavily than the earlier rounds. Of the five who would’ve been ahead of me, three of them had a Final Four of all the #1 seeds. An event that prior to this year had only occurred once in the history of March Madness, was seemingly likely enough for all three to pick it. On top of that, six out of the sixteen had Florida winning it all, but there’s randomness in that normalcy. Perhaps it’s an indication that the selection committee is getting much better with their seeding, and the chaos will start to vanish from the tournament? Maybe NIL is to blame, and college basketball is doomed to see these more dominant teams run the tournament each year. Who knows? I certainly don’t, but I’ll still be right here making my picks in March along with millions of others.


10 About Me


I am a first year graduate student pursuing my master’s degree in Data Science and Analytics at Clemson University. As the middle of seven children who all pursued different activities growing up outside of Philadelphia, sports have always been a focal point in my life. Applying statistics to sports opened my eyes to the power of data, and brought me to where I am today. The March Madness bracket in particular is a challenge that I would love to continue to take on in order to build my tool set as I dive deeper into this field. Some of the best and brightest have contributed their minds to predicting the outcome of this tournament, and none have succeeded so far. Problems like this are what drives my passion for learning, and I hope to continue to both find and solve these problems as I move towards earning my degree and out into the world.



LS0tDQp0aXRsZTogIkZpbmRpbmcgQ2luZGVyZWxsYSINCmF1dGhvcjogIkNhZWxhbiBDb3luZSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAyDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQo8Y2VudGVyPg0KIVtdKE1hcmNoX01hZG5lc3NfbG9nby5wbmcpDQo8L2NlbnRlcg0KDQo8YnI+DQoNCn4qSW1hZ2UgY291cnRlc3kgb2YgdGhlIE5DQUEqfg0KDQojIEludHJvZHVjdGlvbg0KDQpUaGlzIHByb2plY3Qgd2lsbCBidWlsZCBvbiBvbmUgdGhhdCBJIGJlZ2FuIGluIE1hcmNoIG9mIDIwMjUsIHByZWRpY3RpbmcgdGhlIG91dGNvbWVzIG9mICpNYXJjaCBNYWRuZXNzKiB0b3VybmFtZW50IGdhbWVzLiAqTWFyY2ggTWFkbmVzcyogaXMgYSBzaW5nbGUtZWxpbWluYXRpb24gYmFza2V0YmFsbCB0b3VybmFtZW50IGZlYXR1cmluZyA2OCB0ZWFtcywgd2l0aCByZXByZXNlbnRhdGl2ZXMgZnJvbSBldmVyeSBjb25mZXJlbmNlIGluIERpdmlzaW9uIEkgTkNBQSBiYXNrZXRiYWxsLiBUaGUgNjgtdGVhbSBwb29sIGlzIG5hcnJvd2VkIGRvd24gdG8gNjQgYWZ0ZXIgZWlnaHQgdGVhbXMgcGxheSBlYWNoIG90aGVyIGluIHRoZSAiRmlyc3QgRm91ciIgcm91bmQuIFdpdGhpbiB0aGlzIGZpZWxkIG9mIDY0LCB0aGV5J3JlIHNwbGl0IGJldHdlZW4gZm91ciAicmVnaW9ucyIgb2YgYSBicmFja2V0LCAqKlNvdXRoKiosICoqV2VzdCoqLCAqKkVhc3QqKiwgYW5kICoqTWlkd2VzdCoqLiBUaGUgdGVhbXMgaW4gZWFjaCByZWdpb24gYXJlIHJhbmtlZCBieSB0aGUgTkNBQSBDb21taXR0ZWUgYW5kIGdpdmVuIGEgInNlZWQiIGJldHdlZW4gIzEgYW5kICMxNi4gVGhvc2UgdGVhbXMgYXJlIHRoZW4gbWF0Y2hlZCB1cCBhZ2FpbnN0IGVhY2ggb3RoZXIgc28gdGhhdCAjMSBwbGF5cyAjMTYsICMyIHBsYXlzICMxNSwgIzMgcGxheXMgIzE0LCBhbmQgc28gb24uIFdlJ2xsIHJldmlzaXQgdGhlIHNlZWRpbmcgYW5kIHRlYW0gYnJlYWtkb3duIGxhdGVyLCBidXQgdGhpcyBzaG91bGQgZ2l2ZSB0aG9zZSB1bmZhbWlsaWFyIHdpdGggdGhlIHRvdXJuYW1lbnQgYSBnZW5lcmFsIGlkZWEgb2YgdGhlIGZvcm1hdC4gDQoNCkVhY2ggeWVhciwgb25jZSB0aGUgZmllbGQgb2YgNjQgaXMgZXN0YWJsaXNoZWQsIHRlbnMgb2YgbWlsbGlvbnMgYXJvdW5kIHRoZSB3b3JsZCB0cnkgdGhlaXIgYmVzdCB0byBwcmVkaWN0IHRoZSB3aW5uZXJzIGFuZCBsb3NlcnMgb2YgZWFjaCBnYW1lIGFjcm9zcyBhbGwgNjcgdGhhdCBhcmUgcGxheWVkIHRocm91Z2hvdXQgdGhlIHRvdXJuYW1lbnQsIHdoaWNoIG5hcnJvd3MgdGhlIGZpZWxkIGRvd24gdG8ganVzdCB0d28gdGVhbXMgd2hvIHdpbGwgcGxheSBmb3IgdGhlIE5hdGlvbmFsIENoYW1waW9uc2hpcCB0aXRsZS4gVG8gdGhpcyBkYXksIG5vYm9keSBoYXMgZXZlciBjb3JyZWN0bHkgcHJlZGljdGVkIGFsbCA2NyBvdXRjb21lcyBwZXJmZWN0bHkuIFtBY2NvcmRpbmcgdG8gdGhlIE5DQUFdKGh0dHBzOi8vd3d3Lm5jYWEuY29tL25ld3MvYmFza2V0YmFsbC1tZW4vYnJhY2tldGlxLzIwMjUtMDMtMjMvbG9uZ2VzdC1uY2FhLWJyYWNrZXQtaGFzLWV2ZXItc3RheWVkLXBlcmZlY3QpLCB0aGUgY2xvc2VzdCBhbnlvbmUgaGFzIGV2ZXIgY29tZSB0byBhIHBlcmZlY3QgYnJhY2tldCB3YXMgR3JlZ2cgTmlnbCwgYSBuZXVyb3BzeWNob2xvZ2lzdCBmcm9tIENvbHVtYnVzLCBPaGlvIHdobyBjb3JyZWN0bHkgcHJlZGljdGVkIHRoZSBvdXRjb21lcyBvZiA0OSBzdHJhaWdodCBnYW1lcyBiZWZvcmUgIzMgUHVyZHVlIGRlZmVhdGVkICMyIFRlbm5lc3NlZSBpbiBvdmVydGltZSBvZiB0aGUgc2Vjb25kIGdhbWUgaW4gdGhlIFN3ZWV0IDE2LiANCg0KVGhpcyB5ZWFyLCBJIGRlY2lkZWQgdG8gdGFrZSBhIG1vcmUgYW5hbHl0aWNhbCBhcHByb2FjaCB0byBidWlsZGluZyBteSBvd24gYnJhY2tldC4gQWZ0ZXIgdGhyZWUgZGF5cyBvZiByZXNlYXJjaGluZyBwcmVkaWN0aXZlIHZhbHVlcyBpbiBiYXNrZXRiYWxsLCByZWFkaW5nIHBhcGVycywgYW5kIGpvdXJuYWxpbmcgYWxsIG9mIG15IGZpbmRpbmdzLCBJIGZvdW5kIGEgW2Jsb2cgcG9zdF0oaHR0cHM6Ly93d3cuZGF0YS1hY3Rpb24tbGFiLmNvbS8yMDIxLzExLzIxL3ByZWRpY3RpdmUtYW5hbHl0aWNzLWluLWNvbGxlZ2UtYmFza2V0YmFsbC8pIGZyb20gMjAyMSBhYm91dCBhbiBSIFByb2plY3QgdXNpbmcgYSBiaW5vbWlhbCBkaXN0cmlidXRpb24gYXBwcm9hY2ggSSBoYWRuJ3Qgc2VlbiBhbnl3aGVyZSBlbHNlIGJlZm9yZS4gSSB0cmllZCBteSBiZXN0IHRvIGVtdWxhdGUgdGhhdCBwcm9jZWR1cmUgd2l0aCBteSBsaW1pdGVkIGFiaWxpdGllcyBhdCB0aGUgdGltZSwgYnV0IGluIHRoZSBlbmQgd2FzIHVuc2F0aXNmaWVkIHdpdGggdGhlIHVuY2VydGFpbiBxdWFsaXR5IG9mIG15IHdvcmsuIEkgZWxlY3RlZCBub3QgdG8gZW1iYXJyYXNzIG15c2VsZiBieSBzdWJqZWN0aW5nIHRoaXMgbW9kZWwgdG8gdGhlIHNjcnV0aW55IG9mIG15IHBlZXJzLCBhbmQga2VwdCB0aGUgcmVzdWx0cyBidXJpZWQgaW4gYW4gYWxtb3N0IGluZGVjaXBoZXJhYmxlIHNwcmVhZHNoZWV0LiBUaGlzIHVuY2VydGFpbnR5IHByb3ZlZCB0byBiZSBmb29saXNoLCBob3dldmVyLCBhcyBhbGwgb2YgdGhhdCB3b3JrIGRvbmUgZXhjbHVzaXZlbHkgaW4gTWljcm9zb2Z0IEV4Y2VsIGFuZCBzZXZlcmFsIHBhZ2VzIG9mIGhhbmR3cml0dGVuIG5vdGVzIHdhcyBhYmxlIHRvIGNvcnJlY3RseSBwcmVkaWN0ICoqNTYvNjcqKiBvdXRjb21lcyBhY3Jvc3MgdGhlIGVudGlyZSB0b3VybmFtZW50LiBUaGUgZ29hbCwgdW5mb3J0dW5hdGVseSwgaXMgYSBwZXJmZWN0ICoqNjcvNjcqKi4gVGhpcyBjaGFsbGVuZ2UgaGFzIHN0dW1wZWQgbWF0aGVtYXRpY2lhbnMsIGVjb25vbWlzdHMsIGFuYWx5c3RzLCBhbmQgZXZlcnlkYXkgYmFza2V0YmFsbCBmYW5zIGFsaWtlIGZvciBkZWNhZGVzLiBUaGUgcXVlc3Rpb24gdGhhdCBldmVyeW9uZSBhc2tzIGVhY2ggTWFyY2ggaXMgdGhlIHNhbWUsICJ3aGF0IHRlYW1zIGFyZSBnb2luZyB0byBwdWxsIG9mZiBhbiB1cHNldD8iIA0KDQpJZiBjaG9vc2luZyBhIHBlcmZlY3QgYnJhY2tldCB3ZXJlIGFzIHNpbXBsZSBhcyBwaWNraW5nIHRoZSAiZmF2b3JpdGUiIGluIGVhY2ggZ2FtZSBieSB0aGVpciBzZWVkaW5nLCB3ZSdkIGV4cGVjdCB0byBzZWUgYSBGaW5hbCBGb3VyIG9mIGZvdXIgIzEgc2VlZHMgZXZlcnkgeWVhciwgYnV0IHdlIGtub3cgdGhhdCdzIG5vdCB0aGUgY2FzZS4gSW4gZmFjdCwgaXQncyBvbmx5IGhhcHBlbmVkIHR3aWNlOiAqKjIwMDgqKidzIEZpbmFsIEZvdXIgZmVhdHVyZWQgIzEgc2VlZHMgS2Fuc2FzLCBNZW1waGlzLCBOb3J0aCBDYXJvbGluYSwgYW5kIFVDTEEuIFRoZSBvbmx5IG90aGVyIHllYXIgaXQncyBoYXBwZW5lZD8gKioyMDI1KiouIFRoaXMgeWVhcidzIEZpbmFsIEZvdXIgb2YgIzEgc2VlZHMgQXVidXJuLCBEdWtlLCBGbG9yaWRhLCBhbmQgSG91c3RvbiBhY2hpZXZlZCB0aGF0IGZlYXQgZm9yIGp1c3QgdGhlIHNlY29uZCB0aW1lIGV2ZXIuIERlc3BpdGUgdGhpcywgd2UgZW50ZXIgdGhlIDIwMjUtMjYgQ29sbGVnZSBCYXNrZXRiYWxsIHNlYXNvbiB3aXRoIG5vYm9keSBldmVyIGNvcnJlY3RseSBjcmFmdGluZyBhIHBlcmZlY3QgYnJhY2tldC4gDQoNClNvLCB3aGF0IHRlYW1zIHB1bGxlZCBvZmYgYW4gInVwc2V0Ij8gVG8gYW5zd2VyIHRoYXQgcXVlc3Rpb24gd2UgZmlyc3QgbmVlZCB0byBzcGxpdCBpdCBpbnRvIHR3byBwYXJ0cy4gV2hpY2ggdGVhbXMgd2VyZSAqYWN0dWFsbHkqIGZhdm9yZWQgaW4gZWFjaCBnYW1lLCBhbmQgd2hvIHdvbj8gVGhlIGxhdHRlciBpcyBlYXN5IHRvIGFuc3dlciwgYXMgZWFjaCBnYW1lIHdhcyBwbGF5ZWQgaW4gTWFyY2gvQXByaWwgb2YgMjAyNSwgYW5kIHdlIGhhdmUgYWxsIHRoZSByZXN1bHRzIHJlYWRpbHkgYXZhaWxhYmxlLiBUaGUgZm9ybWVyLCBub3Qgc28gbXVjaC4gSW4gb3JkZXIgdG8gc3RhcnQgYW5zd2VyaW5nIHRoYXQgcXVlc3Rpb24sIGxldCdzIHNldCB0aGUgc3RhZ2UuDQoNCjxicj4NCg0KIyBUaGUgQnJhY2tldA0KDQpFYWNoIHRlYW0gaW4gdGhlICpNYXJjaCBNYWRuZXNzKiB0b3VybmFtZW50IGlzIHZ5aW5nIGZvciBhIGNoYW5jZSB0byBwbGF5IGluIHRoZSBOYXRpb25hbCBDaGFtcGlvbnNoaXAuIFRob3NlIDY4IHRlYW1zIGFyZSBzZWxlY3RlZCBmcm9tIHRoZSBwb29sIG9mIGFsbCAzNjQgRGl2aXNpb24gSSB0ZWFtcyBpbiB0aGUgTkNBQS4gRWFjaCBvZiB0aGUgMzY0IHNjaG9vbHMgYXJlIHNwbGl0IGludG8gMzEgZGlmZmVyZW50IGNvbmZlcmVuY2VzLCB3aG8gcHJpbWFyaWx5IGNvbXBldGUgYWdhaW5zdCB0aGUgb3RoZXIgbWVtYmVycyBvZiB0aGVpciBjb25mZXJlbmNlIGluIHRoZSByZWd1bGFyIHNlYXNvbi4gQXQgdGhlIGNvbmNsdXNpb24gb2YgdGhlIHJlZ3VsYXIgc2Vhc29uIGVhY2ggY29uZmVyZW5jZSBob3N0cyB0aGVpciBvd24gc2luZ2xlLWVsaW1pbmF0aW9uIHRvdXJuYW1lbnQsIGFuZCB0aGUgd2lubmVyIG9mIHRoYXQgdG91cm5hbWVudCByZWNlaXZlcyBhbiAiYXV0b21hdGljIGJpZCIgdG8gcGxheSBpbiB0aGUgKk1hcmNoIE1hZG5lc3MqIHRvdXJuYW1lbnQuIFRoZSByZW1haW5pbmcgMzcgc3BvdHMgaW4gdGhlIHRvdXJuYW1lbnQgYXJlIGRlY2lkZWQgYnkgdGhlIE5DQUEgQ29tbWl0dGVlLCB3aG8gYXdhcmRzICJhdC1sYXJnZSIgYmlkcy4gVGhlc2UgZ28gdG8gd2hpY2hldmVyIHRlYW1zIHRoZXkgZGVlbSB0byBiZSB0aGUgMzcgYmVzdCBpbiB0aGUgY291bnRyeSwgYnV0IGRpZG4ndCB3aW4gdGhlaXIgY29uZmVyZW5jZSBhbmQgcmVjZWl2ZSBhbiBhdXRvbWF0aWMgYmlkLiANCg0KRm9yIGEgbnVtYmVyIG9mIHJlYXNvbnMsIHRoaXMgc2VsZWN0aW9uIHByb2Nlc3MgaXMgd2hlcmUgdGhlICJtYWRuZXNzIiBiZWdpbnMuIEFueSB0ZWFtIGluIHRoZSBjb3VudHJ5LCByZWdhcmRsZXNzIG9mIGhvdyBiYWQgdGhleSB3ZXJlIHRocm91Z2hvdXQgdGhlIHJlZ3VsYXIgc2Vhc29uLCBqdXN0IG5lZWRzIHRvIHF1YWxpZnkgZm9yIHRoZWlyIGNvbmZlcmVuY2UgdG91cm5hbWVudCB0byBoYXZlIGEgc2hvdCBhdCBkYW5jaW5nLiBJZiB0aGV5IGNhbiBnZXQgaG90IGluIHRoZWlyIGNvbmZlcmVuY2UgdG91cm5hbWVudCBhbmQgd2luIGl0LCB0aGV5IHJlY2VpdmUgYW4gYXV0b21hdGljIGJpZCBhbGwgdGhlIHNhbWUuIFdlJ2xsIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhIGluIHRoZSBuZXh0IHNlY3Rpb24gYW5kIHdoZXJlIGl0IGNvbWVzIGZyb20sIGJ1dCBvbmUgb2YgdGhlICJ3b3JzdCIgdGVhbXMgaW4gdGhlIHRvdXJuYW1lbnQgdGhpcyB5ZWFyLCB0aGUgU2FpbnQgRnJhbmNpcyBSZWQgRmxhc2gsIGhhZCBhIHBlZGVzdHJpYW4gMTMtMTcgb3ZlcmFsbCByZWNvcmQgaGVhZGluZyBpbnRvIHRoZSBOb3J0aGVhc3QgQ29uZmVyZW5jZSAoTkVDKSBUb3VybmFtZW50LiBEZXNwaXRlIHRoaXMsIHRoZXkgd2VyZSBhYmxlIHRvIHNlY3VyZSB3aW5zIG92ZXIgV2FnbmVyLCBMSVUsIGFuZCBDZW50cmFsIENvbm5lY3RpY3V0IHRvIHdpbiB0aGUgTkVDIGFuZCBwdW5jaCB0aGVpciB0aWNrZXQgdG8gYmUgYSBwYXJ0IG9mIHRoZSBtYWRuZXNzLiANCg0KQXMgd2UgY2FuIHNlZSwgdGhlIGF1dG8tYmlkIHN5c3RlbSBpbnRyb2R1Y2VzIGEgbGV2ZWwgb2YgY2hhb3MgaW4gdGVybXMgb2YgKndobyogaXMgYWJsZSB0byBxdWFsaWZ5IGZvciB0aGUgdG91cm5hbWVudC4gTW91bnQgU3QuIE1hcnkncywgYW5vdGhlciBhdXRvLWJpZCB0ZWFtIG91dCBvZiB0aGUgTUFBQyAoTWV0cm8gQXRsYW50aWMgQXRobGV0aWMgQ29uZmVyZW5jZSkgd2FzIG1hdGNoZWQgdXAgd2l0aCBibHVlLWJsb29kIGJhc2tldGJhbGwgcHJvZ3JhbSBEdWtlIGluIHRoZSBSb3VuZCBvZiA2NC4gV2l0aCBhbiB1bmRlcmdyYWR1YXRlIHN0dWRlbnQgYm9keSBvZiAxLDgxNSwgTW91bnQgU3QuIE1hcnkncyBoYXMgYWJzb2x1dGVseSBubyBidXNpbmVzcyBwbGF5aW5nIER1a2UgaW4gYSBuYXRpb25hbGx5IHRlbGV2aXNlZCBiYXNrZXRiYWxsIGdhbWUsIGFuZCBzdWZmZXJlZCBhbiB1bmNvbXBldGl0aXZlIDkzLTQ5IGRlZmVhdC4gRGVzcGl0ZSB0aGUgY2xlYXIgZGlzY3JlcGFuY2llcyBpbiBzb21lIG1hdGNodXBzLCB0aGUgYXV0by1iaWQgc3lzdGVtIGFmZm9yZHMgdGhlIHNtYWxsZXIgY29uZmVyZW5jZXMvc2Nob29scyBhbiBlcXVhbCBvcHBvcnR1bml0eSB0byBtYWtlIGFuIGFwcGVhcmFuY2UgaW4gdGhlIHRvdXJuYW1lbnQuIA0KDQpXaGVuIGEgbmF0aW9uYWwgcG93ZXJob3VzZSBsaWtlIER1a2Ugc3F1YXJlcyBvZmYgYWdhaW5zdCBhIHNtYWxsLCBwcml2YXRlLCBsaWJlcmFsIGFydHMgc2Nob29sIGZyb20gcnVyYWwgTWFyeWxhbmQsIHdlIGNhbiByZWFzb25hYmx5IGFzc3VtZSB3aG8ncyBnb2luZyB0byB3aW4gdGhhdCBnYW1lLiBXaGlsZSB0aGF0J3Mgbm90IGFsd2F5cyB0aGUgY2FzZSAoc2VlIDIwMTggIzEgVmlyZ2luaWEgdnMuICMxNiBVTUJDLCBhbm90aGVyICMxNiBzZWVkIGZyb20gTWFyeWxhbmQgd2hvIGFjaGlldmVkIGEgbXVjaCBkaWZmZXJlbnQgcmVzdWx0KSwgd2UgZ2VuZXJhbGx5IGV4cGVjdCB0aGUgc21hbGxlciBjb25mZXJlbmNlcyB0byBzdHJ1Z2dsZSBhZ2FpbnN0IHRoZWlyIG11Y2ggbGFyZ2VyIGNvdW50ZXJwYXJ0cy4gVGhlIGF0LWxhcmdlIGJpZCBzeXN0ZW0sIG9uIHRoZSBvdGhlciBoYW5kLCBpbnRyb2R1Y2VzIGEgY29uc2lkZXJhYmxlIGFtb3VudCBvZiB1bmNlcnRhaW50eSB0byB0aGUgYnJhY2tldCBmb3IgYSBkaWZmZXJlbnQgcmVhc29uLiBUaGUgTkNBQSBDb21taXR0ZWUncyBleGFjdCBhcHByb2FjaCB0byBkZXRlcm1pbmluZyB0aGUgMzcgImJlc3QiIHJlbWFpbmluZyBzY2hvb2xzIGluIHRoZSBjb3VudHJ5LCBhZnRlciBhbGwgdGhlIGF1dG8tYmlkcyBoYXZlIGJlZW4gYXdhcmRlZCwgaGFzIGJlZW4gdGhlIHN1YmplY3Qgb2YgbXVjaCBkZWJhdGUgdGhyb3VnaG91dCB0aGUgdG91cm5hbWVudCdzIGVudGlyZSBleGlzdGVuY2UuIFdlIGNhbiByZWFzb25hYmx5IGFzc3VtZSB0aGF0IHRoZXkgdXNlIG11Y2ggb2YgdGhlIHNhbWUgY3JpdGVyaWEgdGhhdCB3ZSB3aWxsIHVzZSBpbiBvdXIgb3duIGRhdGEsIGJ1dCB0aGV5IGhhdmUgYW4gaWxsdXN0cmlvdXMgaGlzdG9yeSBvZiBiZWluZyAid3JvbmciIHdoZW4gbWFraW5nIHRob3NlIHNlbGVjdGlvbnMuIFNpbmNlIHRoZSBzZWxlY3Rpb24gcHJvY2VzcyBvZiBhdC1sYXJnZSBiaWRzIGlzbid0IHRoZSB0b3BpYyBvZiB0aGlzIHByb2plY3QsIHdlIHdvbid0IGdvIHRvbyBpbi1kZXB0aCBpbnRvIHdobyByZWNlaXZlcyB0aGVtLiBBbGwgd2UgbmVlZCB0byB1bmRlcnN0YW5kIGFib3V0IHRoZXNlIGF0LWxhcmdlIHRlYW1zIGlzIHRoYXQgdGhleSBhcmUgYmVsaWV2ZWQgdG8gaGF2ZSAqZWFybmVkKiB0aGVpciBiaWQgdGhyb3VnaCB0aGVpciBwbGF5IGFjcm9zcyB0aGUgZW50aXJlIHNlYXNvbiwgYW5kIHRoZWlyIHNlZWRpbmcgc2hvdWxkIHJlZmxlY3QgaG93IGdvb2Qgb2YgYSB0ZWFtIHRoZXkgYXJlLiBGb3IgaW5zdGFuY2UsIEF1YnVybiBsb3N0IGluIHRoZSBzZW1pZmluYWxzIG9mIHRoZSBTRUMgKFNvdXRoZWFzdGVybiBDb25mZXJlbmNlKSBUb3VybmFtZW50IHRvIFRlbm5lc3NlZS4gQWZ0ZXIgdGhleSBib3RoIHJlY2VpdmVkIGF0LWxhcmdlIGJpZHMsIEF1YnVybiB3YXMgZ2l2ZW4gYSAjMSBzZWVkLCBUZW5uZXNzZWUgYSAjMiBzZWVkLiANCg0KPGJyPg0KDQojIFRoZSBEYXRhDQoNCk5vdyB0aGF0IHdlIGhhdmUgYSBnZW5lcmFsIHVuZGVyc3RhbmRpbmcgb2Ygd2hhdCBzb3J0IG9mIHRlYW1zIG1ha2UgdGhlIHRvdXJuYW1lbnQsIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhIHdlJ2xsIGJlIHVzaW5nLiBUaGUgZmlyc3QsIG1vc3QgaW1wb3J0YW50IGRhdGFzZXQgd2UgaGF2ZSBhdCBvdXIgZGlzcG9zYWwgaXMgS2VuIFBvbWVyb3kncyAqKktlblBvbSoqIHJhbmtpbmdzLiBUaGVzZSBhcmUgdGhlIG51bWJlcnMgd2UnbGwgYmUgdXNpbmcgdG8gZG8gbW9zdCBvZiBvdXIgc2NvcmUgcHJlZGljdGlvbnMuIEFzIHBlciB0aGUgVGVybXMgb2YgVXNlIGZvciB0aGlzIGRhdGEsIGhlcmUgaXMgYSBsaW5rIHRvIHRoZSBbS2VuUG9tIFdlYnNpdGVdKGh0dHBzOi8va2VucG9tLmNvbS8pLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgV2UgdXNlIHRoZSB0aWR5dmVyc2UgYW5kIERUIHBhY2thZ2VzIHRvIGRpc3BsYXkgb3VyIGRhdGEgaW4gYSBjbGVhbmVyIGZvcm1hdCBhcyB3ZSB3b3JrIHRocm91Z2ggaXQgDQojIGFsbC4gV2UgYWxzbyB1c2UgdGhlIHRpZHl2ZXJzZSBtdWNoIGxhdGVyIGluIHRoZSByZXBvcnQgdG8gY3JlYXRlIHNvbWUgdXNlZnVsIGdyYXBocyB0byBkcmF3IGluc2lnaHRzIA0KIyBhYm91dCBvdXIgZGF0YS4NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShEVCkNCiMgSSBpbml0aWFsbHkgdXNlZCBkcGx5ciBmb3Igc29tZSBkYXRhIHRyYW5zZm9ybWluZyBzdGVwcywgYnV0IG5vdyBpdCBleGlzdHMgb25seSB0byBpbnRlcmFjdCB3aXRoIG91ciANCiMgRFQgcGFja2FnZSwgDQpsaWJyYXJ5KGRwbHlyKQ0KIyBUaGlzIHdhcyBhIHBhY2thZ2UgSSBmb3VuZCBieSBhY2NpZGVudGFsbHkgY29uZnVzaW5nIFB5dGhvbiBhbmQgUiBzeW50YXgsIGJ1dCBpdCdzIGluY3JlZGlibHkgdXNlZnVsIA0KIyBmb3IgZGlzcGxheWluZyB0aGUgcmVzdWx0cyBvZiBvdXIgcHJlZGljdGlvbiBtb2RlbCB0aGF0IHdlJ2xsIGJlIHVzaW5nIHF1aXRlIGEgYml0IGxhdGVyLiANCmxpYnJhcnkoZ2x1ZSkNCiMgSW4gb3JkZXIgdG8gcG9pbnQgb3V0IGEgbnVtYmVyIG9mIHRlYW1zIGluIHRoZSBwbG90cyB3ZSdsbCBiZSBidWlsZGluZyB0byB0cnkgYW5kIHNldCBhcGFydCBzb21lIA0KIyBzcGVjaWZpYyB3aW5uZXJzIGFuZCBsb3NlcnMsIHdlIHVzZSBnZ2hpZ2hsaWdodCB0byBtYWtlIHRoZW0gc3RhbmQgb3V0IGFtb25nc3QgdGhlIGVudGlyZSBmaWVsZCBvZiA2NA0KbGlicmFyeShnZ2hpZ2hsaWdodCkNCmxpYnJhcnkoY2JicGxvdFIpDQoNCiMgUmVhZHMgaW4gb3VyIGZpcnN0IGRhdGFzZXQgYW5kIGZvcm1hdHMgaXQgbmljZWx5IGludG8gYSByZWFkYWJsZSBkYXRhdGFibGUNCmtwIDwtIHJlYWRfY3N2KCdrZW5wb20uY3N2JywgY29sX25hbWVzPVRSVUUpDQpkYXRhKGtwLCBwYWNrYWdlPSdnZ3Bsb3QyJykNCmRhdGF0YWJsZShrcCwgDQogICAgICAgICAgZXh0ZW5zaW9ucz0nU2Nyb2xsZXInLA0KICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFg9VFJVRSkpDQpgYGANCg0KPGJyPg0KDQoNClRoZXJlJ3MgYSBmZXcgdmFyaWFibGVzIGluIHRoaXMgZGF0YSB0aGF0IHdlIGRvbid0IG5lZWQsIHNvIHdlIGNhbiBzYWZlbHkgZ2V0IHJpZCBvZiB0aGVtLiBUaGUgb25seSBudW1iZXJzIHdlJ2xsIGJlIHVzaW5nIGZvciBub3cgYXJlIGBPUnRnYCwgYERSdGdgLCBhbmQgYEFkalRgLiBJdCBtYXkgbm90IHNlZW0gbGlrZSBtdWNoLCBidXQgdGhlc2UgdmFsdWVzIHJlcHJlc2VudCBhbG1vc3QgYWxsIHdlIG5lZWQgdG8gbWFrZSBzb21lIHN1cnByaXNpbmdseSBhY2N1cmF0ZSBhc3N1bXB0aW9ucyBhYm91dCBob3cgdGhlc2UgZ2FtZXMgd2lsbCBnby4gDQoNCiogYE9SdGdgIC0gQSBtZWFzdXJlIG9mIG9wcG9uZW50LWFkanVzdGVkIG9mZmVuc2l2ZSBlZmZpY2llbmN5LCBob3cgbWFueSBwb2ludHMgYSB0ZWFtIHNjb3JlcyBwZXIgMTAwIHBvc3Nlc3Npb25zLg0KDQoqIGBEUnRnYCAtIEEgbWVhc3VyZSBvZiBvcHBvbmVudC1hZGp1c3RlZCBkZWZlbnNpdmUgZWZmaWNpZW5jeSwgaG93IG1hbnkgcG9pbnRzIGEgdGVhbSBhbGxvd3MgcGVyIDEwMCBwb3NzZXNzaW9ucy4gDQoNCiogYEFkalRgIC0gQSBtZWFzdXJlIG9mIG9wcG9uZW50LWFkanVzdGVkICJ0ZW1wbywiIGhvdyBtYW55IHBvc3Nlc3Npb25zIGEgdGVhbSBoYXMgcGVyIDQwIG1pbnV0ZXMuIA0KDQo8YnI+DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyBSZW5hbWVzIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyB3ZSBuZWVkIHRoYXQgc2hhcmVkIGR1cGxpY2F0ZSBoZWFkZXJzIHdpdGggb3RoZXJzDQprcDEgPC0ga3AgfD4NCiAgcmVuYW1lKE9SdGcgPSBPUnRnLi4uNiwgRFJ0ZyA9IERSdGcuLi43KQ0KDQojIFJlbW92ZXMgdGhlIHZhcmlhYmxlcyB3ZSBkb24ndCBuZWVkIGZvciB0aGlzIHBhcnRpY3VsYXIgYW5hbHlzaXMNCmtwMiA8LSBrcDEgfD4NCiAgc2VsZWN0KC0oQ29uZjpOZXRSdGcuLi41KSwgLShMdWNrOk5ldFJ0Zy4uLjEzKSkNCg0KIyBPbmNlIGFnYWluIHVzZXMgdGhlIERUIHBhY2thZ2UgdG8gZGlzcGxheSBvdXIgZGF0YSBpbiBhIHJlYWRhYmxlIGRhdGF0YWJsZQ0KZGF0YShrcDIsIHBhY2thZ2U9J2dncGxvdDInKQ0KZGF0YXRhYmxlKGtwMiwgDQogICAgICAgICAgZXh0ZW5zaW9ucz0nU2Nyb2xsZXInLA0KICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFg9VFJVRSkpDQpgYGANCg0KPGJyPg0KDQpCZWZvcmUgd2UgbW92ZSBvbiwgd2UncmUgZ29pbmcgdG8gbmVlZCBhIGZldyBhdmVyYWdlcyBmcm9tIHRoaXMgZGF0YSB0byBiZSB1c2VkIGxhdGVyIGFzIHdlbGwgLiBFYWNoIG9mIHRoZW0gd2lsbCBiZSBkaXNjdXNzZWQgbGF0ZXIsIGJ1dCBmb3Igbm93IHRoZSBhdmVyYWdlcyB3ZSBuZWVkIGFyZToNCg0KKiBgQWRqVG5jYWFgDQoNCiogYGVGR09uY2FhYCANCg0KKiBgZUZHRG5jYWFgIA0KDQoqIGBEUnRnbmNhYWANCg0KKiBgcHBwbmNhYWANCg0KYGVGR09uY2FhYCBhbmQgYGVGR0RuY2FhYCBhcmUgdHdvIGZpZ3VyZXMgSSBjYWxjdWxhdGVkIHNlcGFyYXRlbHkgb3V0c2lkZSBvZiB0aGlzIHdvcmsgYW5kIGhhdmUgb24gaGFuZCwgc28gSSdsbCBiZSBhc3NpZ25pbmcgdGhvc2UgdmFsdWVzIG1hbnVhbGx5LiBUaGV5IGNvbWUgZnJvbSBUZWFtUmFua2luZ3MsIHdoaWNoIGlzIGludHJvZHVjZWQgYmVsb3cuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGaW5kaW5nIC8gYXNzaWduaW5nIGFsbCBvZiB0aGUgYXZlcmFnZSB2YWx1ZXMgd2UnbGwgbmVlZCBsYXRlcg0KDQpBZGpUbmNhYSA8LSBtZWFuKGtwMiRBZGpUKQ0KDQplRkdPbmNhYSA8LSAwLjUwNzYNCg0KZUZHRG5jYWEgPC0gMC41MDk2DQoNCkRSdGduY2FhIDwtIG1lYW4oa3AyJERSdGcpDQoNCnBwcE9uY2FhIDwtIG1lYW4oa3AyJE9SdGcgLyAxMDApDQpgYGANCg0KPGJyPg0KDQpOb3cgdGhhdCB3ZSBoYXZlIHRoZSBLZW5Qb20gZGF0YSwgd2UncmUgZ29pbmcgdG8gbmVlZCBzb21lIG1vcmUgdGVhbS1zcGVjaWZpYyBkYXRhLiBUaGVzZSBhcmUgYWxsIG51bWJlcnMgdGhhdCBJIGNvbGxlY3RlZCBtYW51YWxseSwgdGVhbSBieSB0ZWFtLCBpbiBNYXJjaCBmcm9tIHRoZSBvZmZpY2lhbCBbTkNBQSBTdGF0aXN0aWNzXShodHRwczovL3N0YXRzLm5jYWEub3JnL3NlbGVjdGlvbl9yYW5raW5ncy9uaXR0eV9ncml0dGllcy80MzMzNCkgd2Vic2l0ZSBhbmQgW1RlYW1SYW5raW5nc10oaHR0cHM6Ly93d3cudGVhbXJhbmtpbmdzLmNvbS8pLCBhbmQgdGhleSdyZSBhbHJlYWR5IHN1YnNldCB0byBqdXN0IHRoZSB0ZWFtcyB0aGF0IHBsYXllZCBpbiB0aGUgMjAyNSAqTWFyY2ggTWFkbmVzcyogdG91cm5hbWVudC4gU2luY2Ugd2Ugb25seSB3YW50IHRvIGxvb2sgYXQgdGhpcyBzdWJzZXQgZGF0YSwgd2UgY2FuIHVzZSBhbiBpbm5lciBqb2luIHRvIGdldCB0aGUgYWxtb3N0IGNvbXBsZXRlLCBjb3JyZWN0bHkgc3Vic2V0IGRhdGEgd2UgbmVlZCBjb250YWluaW5nIGp1c3QgdGhlIDY4IHRlYW1zIGluIHRoZSB0b3VybmFtZW50IHRoaXMgeWVhci4NCg0KPGJyPg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgUmVhZHMgaW4gb3VyIHRlYW0gc3RhdGlzdGljcyBhbmQgam9pbnMgaXQgd2l0aCBvdXIga2VucG9tIGRhdGEgc28gd2UgaGF2ZSBldmVyeXRoaW5nIGluIG9uZSBwbGFjZQ0KdGVhbXN0YXRzIDwtIHJlYWRfY3N2KCd0ZWFtX3N0YXRzLmNzdicsICkNCnN0YXRzIDwtIGlubmVyX2pvaW4odGVhbXN0YXRzLCBrcDIsIGJ5ID0gJ3RlYW0nKQ0KDQojIExpa2UgYmVmb3JlLCBkaXNwbGF5cyBhbGwgb3VyIGRhdGEgaW4gYSBjbGVhbiwgcmVhZGFibGUsIGRhdGF0YWJsZQ0KZGF0YShzdGF0cywgcGFja2FnZT0nZ2dwbG90MicpDQpkYXRhdGFibGUoc3RhdHMsIA0KICAgICAgICAgIGV4dGVuc2lvbnM9J1Njcm9sbGVyJywNCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzY3JvbGxYPVRSVUUpKQ0KYGBgDQoNCjxicj4NCg0KTm93LCB0aGlzIGlzIGEgZmFpciBhbW91bnQgb2YgdGVhbSBzdGF0aXN0aWNzLiBSZWFsaXN0aWNhbGx5IHdlIGRvbid0IG5lZWQgYWxsIG9mIGl0IHRvIGZpZ3VyZSBvdXQgb3VyIGV4cGVjdGVkIHdpbm5lcnMgYW5kIGxvc2Vycy4gQnV0LCB3ZSdsbCBiZSB0YWtpbmcgYSBsb29rIGF0IHNvbWUgb2YgdGhlIHN0YXRzIHdlIGRpZG4ndCB1c2UgbGF0ZXIgdG8gZmlndXJlIG91dCBpZiBzb21ldGhpbmcgd2FzIG1pc3NpbmcgZnJvbSBvdXIgcHJlZGljdGlvbnMsIGFuZCBob3cgd2UgY2FuIGJldHRlciBwcmVkaWN0IHdpbm5lcnMgYW5kIGxvc2VycyBpbiB0aGUgZnV0dXJlLiANCg0KSW4gYWRkaXRpb24gdG8gd2hhdCB3ZSBoYXZlIGFscmVhZHksIHdlJ3JlIGdvaW5nIHRvIGNhbGN1bGF0ZSBhIGZldyBtb3JlIHN0YXRzIHRoYXQgd2UgY2FuIHVzZS4gVGhlIGZpcnN0IG9mIHRoZXNlIGlzIGBwcHBPYCBhbmQgYHBwcERgLCB3aGljaCBhcmUgUG9pbnRzIHBlciBQb3NzZXNzaW9uIG9uIGJvdGggb2ZmZW5zZSBhbmQgZGVmZW5zZSwgcmVzcGVjdGl2ZWx5LiBUaGlzIGlzIHdoZXJlIHRoZSBLZW5Qb20gZGF0YSBiZWdpbnMgdG8gZGVtb25zdHJhdGUgaG93IHVzZWZ1bCBpdCBpcy4gVGhlIGBPUnRnYCBhbmQgYERSdGdgIHN0YXRpc3RpY3MgYXJlIG9wcG9uZW50IGFkanVzdGVkIGVmZmljaWVuY2llcyBmb3IgYm90aCBwb2ludHMgc2NvcmVkIG9uIG9mZmVuc2UgYW5kIGFsbG93ZWQgb24gZGVmZW5zZSByZXNwZWN0aXZlbHksIHBlci0xMDAgcG9zc2Vzc2lvbnMuIFRoZXJlZm9yZSwgd2UgY2FuIGRpdmlkZSB0aG9zZSBudW1iZXJzIGJ5IDEwMCB0byBnZXQgb3VyIGBwcHBPYCBhbmQgYHBwcERgLiANCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgR2l2ZXMgdXMgYSBwZXItcG9zc2Vzc2lvbiBhbHRlcm5hdGl2ZSB0byBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSBlZmZpY2llbmN5LCByYXRoZXIgDQojIHRoYW4gcGVyLTEwMCBwb3NzZXNzaW9ucw0Kc3RhdHMxIDwtIHN0YXRzIHw+DQogIG11dGF0ZShwcHBPID0gT1J0ZyAvIDEwMCwNCiAgICAgICAgIHBwcEQgPSBEUnRnIC8gMTAwKQ0KYGBgDQoNCjxicj4NCg0KV2hpbGUgaW4gb3VyIGV4cGVjdGVkIHBvaW50cyBjYWxjdWxhdGlvbnMgd2Ugd29uJ3QgYmUgdXNpbmcgdGhlc2UgYHBwcE9gIGFuZCBgcHBwRGAgZmlndXJlcyB0aGVtc2VsdmVzLCBvcHRpbmcgdG8gdXNlIHRoZSBgT1J0Z2AgYW5kIGBEUnRnYCBpbnN0ZWFkLCB0aGV5IG1pZ2h0IHByb3ZlIHVzZWZ1bCB3aGVuIHdlIHRha2UgYSBsb29rIGF0IHRoZSAidXBzZXRzIiBhZnRlciBjcmVhdGluZyBvdXIgYnJhY2tldCBzaW11bGF0aW9uLiBXZSdyZSBhbHNvIGdvaW5nIHRvIGNyZWF0ZSB0aHJlZSBtb3JlIHZhbHVlcyB0aGF0IG1heSBwcm92ZSB1c2VmdWwgbGF0ZXIgYXMgd2VsbC4gVGhlc2UgYXJlOiANCg0KKiBgZXByYCAoRWZmZWN0aXZlIFBvc3Nlc3Npb24gUmF0aW8pIC0gVGhlIG51bWJlciBvZiBzaG90IG9wcG9ydHVuaXRpZXMgYSB0ZWFtIGhhcyBwZXIgcG9zc2Vzc2lvbi4NCg0KKiBgdHNgIChUcnVlIFNob290aW5nKSAtICBTaW5jZSBiYXNrZXRiYWxsIGlzIHNjb3JlZCBpbiBpbmNyZW1lbnRzIG9mIDEsIDIsIGFuZCAzLCBgdHNgIHRlbGxzIHVzIHRoZSBwb2ludHMgcGVyIHNob3Qgb3Bwb3J0dW5pdHkgdGhhdCBlYWNoIHRlYW0gaGFzLiBUaGUgY29uc3RhbnQgMC40NzUgZXhpc3RzIGluIHRoZSBjYWxjdWxhdGlvbiBmb3IgdGhpcyBudW1iZXIgYmVjYXVzZSBvbmx5IGFib3V0IDQ3LjUlIG9mIEZyZWUgVGhyb3dzIGFjdHVhbGx5IGVuZCBhIHBvc3Nlc3Npb24uIERpZmZlcmVudCBzb3VyY2VzIGhhdmUgbGFuZGVkIG9uIGRpZmZlcmVudCBjb25zdGFudHMgdG8gdXNlIGZvciB0aGlzIGZpZ3VyZSwgYnV0IEtlblBvbSB1c2VzIDAuNDc1LCBzbyBJJ3ZlIGVsZWN0ZWQgdG8gc3RpY2sgd2l0aCBpdCBhcyB3ZWxsLg0KDQoqIGBwcHBgIChQb2ludHMgUGVyIFBvc3Nlc3Npb24pIC0gRXZlbiB0aG91Z2ggd2UgYWxyZWFkeSBoYXZlIG91ciBvcHBvbmVudC1hZGp1c3RlZCBgcHBwT2AgZm9yIGVhY2ggdGVhbSwgdGhpcyBmaWd1cmUgZ2l2ZXMgdXMgYW4gb2JqZWN0aXZlIGVzdGltYXRlIG9mIGVhY2ggdGVhbSdzIG9wcG9uZW50LWluZGVwZW5kZW50IHNjb3JpbmcgcHJvd2Vzcy4gSW4gYmFza2V0YmFsbCwgdGVhbXMgaGF2ZSB0aGUgc2FtZSBhbW91bnQgb2YgcG9zc2Vzc2lvbnMgZWFjaCBnYW1lICgrLy0gMSksIHNvIHR5cGljYWxseSB0aGUgdGVhbSB3aXRoIHRoZSBoaWdoZXIgYHBwcGAgd2lucy4gVXNpbmcgYGVwciB4IHRzYCB0byBmaW5kIGBwcHBgIGdpdmVzIHVzIGEgZ29vZCBlc3RpbWF0ZSBvZiBlYWNoIHRlYW0ncyBzY29yaW5nIGFiaWxpdHkuIEl0IGVzc2VudGlhbGx5IHRlbGxzIHVzIGhvdyBvZnRlbiBhIHRlYW0gc2hvb3RzLCBhbmQgaG93IG1hbnkgcG9pbnRzIHdlIGV4cGVjdCBvdXQgb2YgZWFjaCBzaG90LiANCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojIENyZWF0ZXMgb3VyIGVwciwgdHMsIGFuZCBwcHAgdmFyaWFibGVzIGZvciBsYXRlciB1c2UgaWYgbmVlZGVkDQpzdGF0czIgPC0gc3RhdHMxIHw+DQogIG11dGF0ZShlcHIgPSAoKHBvc3MucGVyLmdhbWUgKyByZWIub2ZmKSAtIHRvLmcpIC8gcG9zcy5wZXIuZ2FtZSwNCiAgICAgICAgIHRzID0gc2NvcmluZy5vZmYgLyAoZmdhICsgKDAuNDc1ICogZnRhLmcpKSwNCiAgICAgICAgIHBwcCA9IGVwciAqIHRzKQ0KYGBgDQoNCjxicj4NCg0KV2UnbGwgYmUgY3JlYXRpbmcgYSBmZXcgbW9yZSB2YXJpYWJsZXMgdG8gbG9vayBhdCBvbmNlIHdlIHN0YXJ0IHRvIGRpdmUgaW50byBnYW1lIG91dGNvbWVzLCBhcyB3ZWxsIGFzIG1hdGNodXAgc3BlY2lmaWMgZGlmZmVyZW5jZXMgYmV0d2VlbiB0ZWFtcy4gRm9yIG5vdyB0aGVzZSBudW1iZXJzIGdpdmUgdXMgYSBzb2xpZCBmcmFtZXdvcmsgb2Ygd2hhdCBlYWNoIG9mIHRoZSB0ZWFtcyBpbiB0aGUgdG91cm5hbWVudCBicmluZ3MgdG8gdGhlIHRhYmxlLiANCg0KIyBXaGF0IElzIEEgJ0NpbmRlcmVsbGEgU3Rvcnk/Jw0KDQpJbiB0aGUgbmV4dCBzZWN0aW9ucyB3ZSdsbCB0YWtlIGEgbG9vayBhdCB3aGF0IGFjdHVhbGx5IGhhcHBlbmVkIGluIHRoZSAyMDI1ICpNYXJjaCBNYWRuZXNzKiB0b3VybmFtZW50LCBhbG9uZyB3aXRoIHdoYXQgdGhlIG1vZGVsIEkgbWVudGlvbmVkIGVhcmxpZXIgcHJlZGljdGVkIHdvdWxkIGhhcHBlbi4gQmVmb3JlIHRoYXQsIGhvd2V2ZXIsIEkgd2FudCB0byB0YWtlIGEgc3RlcCBiYWNrIHRvIGVsYWJvcmF0ZSBvbiB0aGUgdGl0bGUgb2YgdGhpcyBwcm9qZWN0LiBBICJDaW5kZXJlbGxhIFN0b3J5IiB0ZWFtIGluICpNYXJjaCBNYWRuZXNzKiB0eXBpY2FsbHkgcmVmZXJzIHRvIGFuIHVuZGVyZG9nLCBoaWdobHktc2VlZGVkIHRlYW0gdGhhdCBtYWtlcyBpdCBtdWNoIGZ1cnRoZXIgaW4gdGhlIHRvdXJuYW1lbnQgdGhhbiBhbnlvbmUgZXhwZWN0cyB0aGVtIHRvLiBXZSd2ZSBhbHJlYWR5IGRpc2N1c3NlZCB3aGljaCB0ZWFtcyBtYWtlIHRoZSB0b3VybmFtZW50LCBidXQgdGhlIHNlZWRpbmcgcHJvY2VzcyBpcyByZWxhdGl2ZWx5IHVua25vd24gb3V0c2lkZSBvZiB0aGUgcm9vbSB3aGVyZSB0aGUgTkNBQSBDb21taXR0ZWUgbWFrZXMgdGhlaXIgZGVjaXNpb25zLiBUaGlzIGlzIHdoZXJlIG91ciBtb2RlbCBkZXZpYXRlcyBmcm9tIHRoZSB0eXBpY2FsIGJyYWNrZXQtbWFrZXIncyBwZXJjZXB0aW9uIG9mIGVhY2ggZ2FtZS4gVGhlcmUgYXJlIG92ZXIgMSwwMDAgY29sbGVnZSBiYXNrZXRiYWxsIGdhbWVzIHBsYXllZCBhY3Jvc3MgdGhlIG5hdGlvbiBwcmlvciB0byAqTWFyY2ggTWFkbmVzcyosIHdoaWNoIGlzIHNpbXBseSB0b28gbWFueSBmb3IgYW55IG9uZSBwZXJzb24gdG8gd2F0Y2ggYWxsIG9mIHRoZW0sIGluY2x1ZGluZyB0aG9zZSBvbiB0aGUgY29tbWl0dGVlLiBUaGlzIGlzIHdoZXJlIHRoZXkgdGVuZCB0byBnZXQgc2VlZGluZyAid3JvbmciLCBhcyBJIGFsbHVkZWQgdG8gZWFybGllci4gV2hpbGUgb25lIHNjaG9vbCBtYXkgdGVjaG5pY2FsbHkgYmUgYmV0dGVyIHRoYW4gYW5vdGhlciBvbiBwYXBlciwgdGhleSBtYXkgbm90IG5lY2Vzc2FyaWx5IGJlIGZhdm9yaXRlcyB0byB3aW4gYWdhaW5zdCBhICJsZXNzZXIiIG9wcG9uZW50Lg0KDQpEdWUgdG8gdGhpcyBzZWVkaW5nLCBldmVuIGJlZm9yZSBhIHNpbmdsZSBnYW1lIGhhcyBiZWVuIHBsYXllZCBpbiB0aGUgUm91bmQgb2YgNjQgdGhlIENvbW1pdHRlZSBpbnRyb2R1Y2VzIGEgYmlhcyBpbiBmYXZvciBvZiBvbmUgdGVhbS4gSWYgeW91IGhhZG4ndCB3YXRjaGVkIGEgY29sbGVnZSBiYXNrZXRiYWxsIGdhbWUgYWxsIHNlYXNvbiwgeW91IG1heSBleHBlY3QgYSAjNyBvciAjMiBzZWVkIHRvIGRlZmVhdCBhICMxMCBzZWVkIHdpdGggcmVsYXRpdmUgZWFzZSwgYnV0IHRoaXMgeWVhciB0aGF0IHdhc24ndCB0aGUgY2FzZS4gRm9yICMxMCBBcmthbnNhcywgdGhleSBkZWZpZWQgdGhlIG9kZHMgaW4gYmFjayB0byBiYWNrIGdhbWVzIGFzIGEgKnRydWUqIENpbmRlcmVsbGEsIG5vdCBmYXZvcmVkIGluIGVpdGhlciBnYW1lIGJ5IHNlZWRpbmcgb3Igb3VyIG1vZGVsLiBUaGlzIGlzIHRoZSB0eXBlIG9mIHRlYW0gd2UncmUgbG9va2luZyB0byBpZGVudGlmeSAqKmJlZm9yZSoqIHRoZXkgYnVzdCBvdXIgYnJhY2tldC4gU28sIHdpdGggdGhhdCBpbiBtaW5kLCBsZXQncyBsb29rIGF0IHRoZSBnYW1lcy4gV2UnbGwgYmVnaW4gaW4gdGhlIFJvdW5kIG9mIDY0Lg0KDQojIFRoZSBNb2RlbA0KDQpTaW5jZSBhbGwgb2YgdGhlIGdhbWVzIGhhdmUgYWxyZWFkeSBiZWVuIHBsYXllZCwgd2UgY2FuIGZpbmQgdGhlIHNjb3JlcyBvbiB0aGUgaW50ZXJuZXQgYW5kIG1ha2UgZGVjbGFyYXRpb25zIGFib3V0IHRoZSBvdXRjb21lIHdpdGggdGhlIHBvd2VyIG9mIGhpbmRzaWdodC4gQnV0IGlmIHdlIHdhbnQgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSBhaGVhZCBvZiB0aW1lLCB3ZSdyZSBnb2luZyB0byBuZWVkIHRvIHVzZSB0aGUgZGF0YSB3ZSBmb3VuZCBlYXJsaWVyIHRvIGZpbmQgb3Bwb25lbnQtYWRqdXN0ZWQgZXhwZWN0ZWQgdmFsdWVzIGZvciBlYWNoIG1hdGNodXAuIFRoZXNlIGVxdWF0aW9ucyBhcmUgdGFrZW4gZGlyZWN0bHkgZnJvbSB0aGUgYmxvZyBwb3N0IG1lbnRpb25lZCBlYXJsaWVyLCB3aXRoIHNvbWUgdmFyaWFibGVzIGFkanVzdGVkIHRvIGNvaW5jaWRlIHdpdGggb3VyIGRhdGEuIFdlJ2xsIHN0YXJ0IHdpdGggdGVtcG86DQoNCiogVXNpbmcgdGhlIGBBZGpUYCB2YWx1ZXMgZnJvbSBvdXIgS2VuUG9tIGRhdGEsIGFzIHdlbGwgYXMgdGhlIE5DQUEgYXZlcmFnZSB0aGF0IHdlIGNhbGN1bGF0ZWQgZWFybGllciwgd2UgY2FuIGVzdGltYXRlIHRoZSAidGVtcG8iIG9mIHRoZSBnYW1lLiBUaGlzIGlzIGEgcHJlZGljdGlvbiBmb3IgaG93IG1hbnkgcG9zc2Vzc2lvbnMgZWFjaCB0ZWFtIHdpbGwgaGF2ZSBwZXIgNDAgbWludXRlcy4gVGVhbXMgdGhhdCBwbGF5IGEgbG93ZXItdGhhbi1hdmVyYWdlIHRlbXBvIHRlbmQgdG8gY29udHJvbCB0aGUgcGFjZSBvZiB0aGUgZ2FtZS4gVGhleSdyZSB1c3VhbGx5IGNoYXJhY3Rlcml6ZWQgYnkgaGF2aW5nIGxvdyBzaG90IHZvbHVtZSwgYnV0IGEgaGlnaCBtYWtlIHBlcmNlbnRhZ2UsIGZhdm9yaW5nIHF1YWxpdHkgc2hvdHMuIFRlYW1zIHdpdGggYSBoaWdoZXItdGhhbi1hdmVyYWdlIHRlbXBvIGFyZSB1c3VhbGx5IHRoZSBvcHBvc2l0ZSwgZmF2b3JpbmcgYSBoaWdoIHNob3Qgdm9sdW1lIGJ1dCBsb3dlciBtYWtlIHBlcmNlbnRhZ2VzLiBUaGVyZSdzIG5vdCBhICJjb3JyZWN0IiB3YXkgdG8gcGxheSBhIGdhbWUgb2YgYmFza2V0YmFsbCwgYnV0IHRoZXNlIGRpZmZlcmVudCB0ZWFtIGlkZW50aXRpZXMgaXMgc29tZXRoaW5nIHdlJ2xsIGludmVzdGlnYXRlIGxhdGVyLiBUaGUgZXhwZWN0ZWQgdGVtcG8gb2YgYSBnYW1lIHBsYXllZCBiZXR3ZWVuICpUZWFtIEEqIGFuZCAqVGVhbSBCKiBpczoNCg0KPGJyPg0KDQp+X18qRXhwZWN0ZWQgVGVtcG8gZm9yIFRlYW0gQSB2cy4gQipfX34NClxiZWdpbnthbGlnbip9DQpFKFRlbXBvX3tBLCBCfSkgPSBcZnJhY3tBZGpUX3tBfX17QWRqVF97TkNBQX19ICogXGZyYWN7QWRqVF97Qn19e0FkalRfe05DQUF9fSAqIEFkalRfe05DQUF9DQpcZW5ke2FsaWduKn0NCg0KPGJyPg0KDQoqIFdlIGNhbiB1c2UgdGhpcyBleHBlY3RlZCB0ZW1wbyB2YWx1ZSB0byBmaW5kIG91ciBuZXh0IGltcG9ydGFudCBmaWd1cmUsIEV4cGVjdGVkIEZpZWxkIEdvYWxzIEF0dGVtcHRlZC4gVGhpcyB3aWxsIGdpdmUgdXMgYSBtZWFzdXJlIG9mIGhvdyBtYW55IHNob3RzICpUZWFtIEEqIGlzIGV4cGVjdGVkIHRvIHRha2UsIG9wcG9uZW50LWFkanVzdGVkIGZvciAqVGVhbSBCKidzIGRlZmVuc2UuIFRoZSBlcXVhdGlvbiB3ZSdsbCB1c2UgaXM6DQoNCn5fXypFeHBlY3RlZCBGaWVsZCBHb2FscyBBdHRlbXB0ZWQgYnkgVGVhbSBBIHZzLiBUZWFtIEIqX19+DQpcYmVnaW57YWxpZ24qfQ0KRShGR0Ffe0F9KSA9IEZHQV97QX0gKiBcZnJhY3tFKFRlbXBvX3tBLCBCfSl9e0FkalRfe0F9fQ0KXGVuZHthbGlnbip9DQoNCiogTmV4dCwgd2UnbGwgY2FsY3VsYXRlIHRoZSBleHBlY3RlZCBgZUZHJWAgKEVmZmVjdGl2ZSBGaWVsZCBHb2FsIFBlcmNlbnRhZ2UpLiBXZSBoYXZlbid0IGV4cGxhaW5lZCBgZUZHJWAgeWV0LCBzbyB3aGF0IGlzIGl0PyBgZUZHJWAgaXMgc2ltaWxhciB0byBhIG1vcmUgY29tbW9uIG1lYXN1cmUsIGBGRyVgLiBgRkclYCBnaXZlcyB0aGUgcGVyY2VudGFnZSBvZiBmaWVsZCBnb2FscyBtYWRlIHBlciBmaWVsZCBnb2FscyBhdHRlbXB0ZWQuKiBgZUZHJWAgaXMgc2xpZ2h0bHkgbW9yZSBudWFuY2VkIHRoYW4gYEZHJWAgYmVjYXVzZSBpdCBhY2NvdW50cyBmb3IgYm90aCAyIGFuZCAzIHBvaW50IGJhc2tldHMuIFdoaWxlIEkgZGlkbid0IGV4cGxpY2l0bHkgY2FsY3VsYXRlIHRoZSBlRkclIHZhbHVlcyBpbiBvdXIgZGF0YXNldCBzaW5jZSB0aGV5J3JlIGF2YWlsYWJsZSBpbiB0aGUgVGVhbVJhbmtpbmdzIGRhdGEsIHRoZSBlcXVhdGlvbiBpcyBnaXZlbiBiZWxvdy4gIA0KDQoqPHN1Yj5UaGlzIGlzIGEgZ29vZCBvcHBvcnR1bml0eSB0byBtZW50aW9uIHRoYXQgaW4gYmFza2V0YmFsbCwgYSAiZmllbGQgZ29hbCIgaXMgc2ltcGx5IGEgc2hvdCBmcm9tIGFueXdoZXJlIG9uIHRoZSBjb3VydCBkdXJpbmcgbm9ybWFsIHBsYXksIGkuZS4gbm90IGEgZnJlZSB0aHJvdy4gVGhlc2UgYXJlIG5vdCB0aGUgc2FtZSBhcyB0aGUgZmllbGQgZ29hbHMgZm91bmQgaW4gZm9vdGJhbGwuPC9zdWI+DQoNCjxicj4NCg0Kfl9fKkVmZmVjdGl2ZSBGaWVsZCBHb2FsIFBlcmNlbnRhZ2UgKGVGRyUpKl9ffg0KXGJlZ2lue2FsaWduKn0NCmVGR1wlXCA9IFxmcmFje0ZHICsoMC41KjNQKX17RkdBfQ0KXGVuZHthbGlnbip9DQoNCn5fXypFeHBlY3RlZCBlRkclIGZvciBUZWFtIEEgdnMuIFRlYW0gQipfX34NClxiZWdpbnthbGlnbip9DQpFKGVGR08pX3tBfSA9IFxmcmFje2VGR09fe0F9fXtlRkdPX3tOQ0FBfX0gKiBcZnJhY3tlRkdEX3tCfX17ZUZHRF97TkNBQX19ICogZUZHT197QX0gKiBcZnJhY3sxfXsxMDB9DQpcZW5ke2FsaWduKn0NCg0KPGJyPg0KDQoqIE9uY2Ugd2UgaGF2ZSBib3RoIG9mIHRob3NlIHZhbHVlcywgd2UnbGwgZmluZCB0aGUgZXhwZWN0ZWQgcG9pbnRzIHNjb3JlZCBieSAqVGVhbSBBKiBhZ2FpbnN0ICpUZWFtIEIqLiBXZSBkbyB0aGlzIGJ5IG11bHRpcGx5aW5nICpUZWFtIEEqJ3MgYWRqdXN0ZWQgZWZmaWNpZW5jeSBvbiBvZmZlbnNlIGJ5ICpUZWFtIEIqJ3MgYWRqdXN0ZWQgZWZmaWNpZW5jeSBhcyB3ZWxsIGFzIHRoZSBleHBlY3RlZCB0ZW1wbyBvZiB0aGUgZ2FtZSB3ZSBjYWxjdWxhdGVkIGVhcmxpZXIsIG92ZXIgdGhlIGF2ZXJhZ2UgTkNBQSBkZWZlbnNpdmUgZWZmaWNpZW5jeS4gU2luY2Ugb3VyIGVmZmljaWVuY2llcyBgT1J0Z2AgYW5kIGBEUnRnYCBmcm9tIHRoZSBLZW5Qb20gcmFua2luZ3MgYXJlIGdpdmVuIGFzIHBvaW50cyBzY29yZWQvYWxsb3dlZCBwZXItMTAwIHBvc3Nlc3Npb25zIGJ5IG5hdHVyZSwgd2UgZW5kIHVwIHdpdGggdGhlIGV4cGVjdGVkIHBvaW50cyBmb3IgZWFjaCB0ZWFtLg0KDQo8YnI+DQoNCn5fXypFeHBlY3RlZCBQb2ludHMgZm9yIFRlYW0gQSB2cy4gVGVhbSBCKl9ffg0KXGJlZ2lue2FsaWduKn0NCkUoUG9pbnRzKV97QX0gPSBcZnJhY3tPUnRnX3tBfSAqIERSdGdfe0J9ICogRShUZW1wb197QSxCfSl9e0RSdGdfe05DQUF9fSAqIFxmcmFjezF9ezEwMH0NClxlbmR7YWxpZ24qfQ0KDQo8YnI+DQoNCkluIG15IGluaXRpYWwgZm9yYXkgaW50byB0aGlzIGJpbm9taWFsIGRpc3RyaWJ1dGlvbiBhcHByb2FjaCwgdGhpcyB3YXMgdGhlIHBvaW50IHdoZXJlIEkgc3RvcHBlZC4gVW5hd2FyZSBvZiBob3cgdG8gZWZmZWN0aXZlbHkgbW9kZWwgdGhlIGRpc3RyaWJ1dGlvbiB1c2luZyB0aGUgdmFyaWFuY2Ugd2UnbGwgbG9vayBhdCBuZXh0LCBJIGRlZW1lZCB0aGUgZXhwZWN0ZWQgc2NvcmUgc3VmZmljaWVudDsgYW5kIHRvIHNvbWUgZXh0ZW50IGl0IHdhcy4gSW4gNTYvNjcgZ2FtZXMgdGhlIHRlYW0gd2hvIHdhcyBleHBlY3RlZCB0byBzY29yZSBtb3JlIHBvaW50cyB1c2luZyB0aGlzIG1ldGhvZCwgZGlkLiBCdXQgdGhpcyB0aW1lIGFyb3VuZCB3ZSdsbCBsb29rIGF0IHRoZSB2YXJpYW5jZSBpbiBvcmRlciB0byBhZGQgd2luIHByb2JhYmlsaXRpZXMgdG8gb3VyIHByZWRpY3Rpb25zLiANCg0KPGJyPg0KDQoqIFRvIGNhbGN1bGF0ZSB0aGUgdmFyaWFuY2UgaW4gc2NvcmluZyBmb3IgKlRlYW0gQSogd2UnbGwgdXNlIHRoZSBmb3JtdWxhIGJlbG93LiBJZiB3ZSB2aWV3IGZpZWxkIGdvYWxzIGF0dGVtcHRlZCBhcyB0cmlhbHMsIGFuZCBvdXIgYGVGRyVgIGFzIHRoZSBwcm9iYWJpbGl0eSBvZiBzdWNjZXNzLCB3ZSBjYW4gZWFzaWx5IGZpbmQgdGhlIHZhcmlhbmNlIGZvciBvdXIgZGlzdHJpYnV0aW9uLiANCg0Kfl9fKkV4cGVjdGVkIFZhcmlhbmNlIGluIFNjb3JpbmcgZm9yIFRlYW0gQSB2cy4gVGVhbSBCKl9ffg0KXGJlZ2lue2FsaWduKn0NClZhcihQb2ludHNfe0F9KSA9IEUoRkdBX3tBfSkgKiBFKGVGR09fe0F9KSgxLWVGR09fe0F9KSAqIDINClxlbmR7YWxpZ24qfQ0KDQo8YnI+DQoNCk5vdyB0aGF0IHdlIGhhdmUgYWxsIHRoZSBlcXVhdGlvbnMgd2UnbGwgbmVlZCwgd2UgY2FuIGJlZ2luIHRvIHN0YXJ0IHB1dHRpbmcgdG9nZXRoZXIgb3VyIGJyYWNrZXQuIA0KDQo8YnI+DQoNCiMgQnVpbGRpbmcgdGhlIEJyYWNrZXQNCg0KVG8gcmVtYWluIHdpdGhpbiB0aGUgc2NvcGUgb2YgdGhpcyBwcm9qZWN0LCBJJ2xsIHJlZnJhaW4gZnJvbSBidWlsZGluZyBhbiBlbnRpcmUgYnJhY2tldCBzaW11bGF0aW9uLiBJbnN0ZWFkLCBvcHRpbmcgdG8gZ28gZ2FtZSBieSBnYW1lIGFuZCBtYW51YWxseSBlbnRlciB0aGUgbWF0Y2h1cHMgZm9yIGVhY2guIEJ1dCBpbiBvcmRlciB0byBkbyB0aGF0IGluIGEgcmVhc29uYWJsZSBhbW91bnQgb2YgdGltZSwgd2UncmUgZ29pbmcgdG8gbmVlZCB0byBwdXQgdG9nZXRoZXIgc29tZSBmdW5jdGlvbnMgdXNpbmcgdGhlIGVxdWF0aW9ucyB3ZSBqdXN0IGRlc2NyaWJlZCBhbmQgdGhlIGF2ZXJhZ2VzIHdlIGNhbGN1bGF0ZWQgZWFybGllci4NCg0KYGBge3J9DQojIEV4cGVjdGVkIFRlbXBvIGZvciBUZWFtIEEgdnMuIEINCmV0ZW1wbyA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1hLCAiQWRqVCJdIC8gQWRqVG5jYWEpICogKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIkFkalQiXSAvIEFkalRuY2FhKSAqIEFkalRuY2FhDQp9DQoNCiMgRXhwZWN0ZWQgRmllbGQgR29hbHMgQXR0ZW1wdGVkIGJ5IFRlYW0gQSB2cy4gVGVhbSBCDQplZmdhYSA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICBzdGF0czJbc3RhdHMyJHRlYW0gPT0gdGVhbWEsICJmZ2EiXSAqIChldGVtcG8odGVhbWEsIHRlYW1iKSAvIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgIkFkalQiXSkNCn0NCg0KIyBFeHBlY3RlZCBGaWVsZCBHb2FscyBBdHRlbXB0ZWQgYnkgVGVhbSBCIHZzLiBUZWFtIEENCmVmZ2FiIDwtIGZ1bmN0aW9uKHRlYW1hLCB0ZWFtYil7DQogIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgImZnYSJdICogKGV0ZW1wbyh0ZWFtYSwgdGVhbWIpIC8gc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1iLCAiQWRqVCJdKQ0KfQ0KDQojIEV4cGVjdGVkIGVGRyUgZm9yIFRlYW0gQSB2cy4gVGVhbSBCDQplZWZnb2EgPC0gZnVuY3Rpb24odGVhbWEsIHRlYW1iKXsNCiAgKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgImVGRyJdIC8gZUZHT25jYWEpICogKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIm9wcC5lRkciXSAvIGVGR0RuY2FhKSAqIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgImVGRyJdDQp9DQoNCiMgRXhwZWN0ZWQgZUZHJSBmb3IgVGVhbSBCIHZzLiBUZWFtIEENCmVlZmdvYiA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1iLCAiZUZHIl0gLyBlRkdPbmNhYSkgKiAoc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1hLCAib3BwLmVGRyJdIC8gZUZHRG5jYWEpICogc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1iLCAiZUZHIl0NCn0NCg0KIyBFeHBlY3RlZCBQb2ludHMgZm9yIFRlYW0gQSB2cy4gVGVhbSBCDQplcG9pbnRzYSA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgIk9SdGciXSAqIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIkRSdGciXSAqIGV0ZW1wbyh0ZWFtYSwgdGVhbWIpKSAvIERSdGduY2FhKSAqICgxLzEwMCkNCn0NCg0KIyBFeHBlY3RlZCBQb2ludHMgZm9yIFRlYW0gQiB2cy4gVGVhbSBBDQplcG9pbnRzYiA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIk9SdGciXSAqIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgIkRSdGciXSAqIGV0ZW1wbyh0ZWFtYSwgdGVhbWIpKSAvIERSdGduY2FhKSAqICgxLzEwMCkNCn0NCg0KIyBFeHBlY3RlZCBWYXJpYW5jZSBpbiBTY29yaW5nIGZvciBUZWFtIEEgdnMuIFRlYW0gQiwgY29udmVydGVkIHRvIGEgbnVtZXJpYyB2YWx1ZSB0byBhdm9pZCBpc3N1ZXMgd2l0aCB0aGUgDQojICdtYXRjaHVwJyBmdW5jdGlvbiBpbnRyb2R1Y2VkIG5leHQNCnZhcnBvaW50c2EgPC0gZnVuY3Rpb24odGVhbWEsIHRlYW1iKXsNCiAgdmFyYSA8LSBlZmdhYSh0ZWFtYSwgdGVhbWIpICogKGVlZmdvYSh0ZWFtYSwgdGVhbWIpKigxIC0gZWVmZ29hKHRlYW1hLCB0ZWFtYikpKSAqIDINCiAgdmEgPC0gYXMubnVtZXJpYyh2YXJhKQ0KICByZXR1cm4odmEpDQp9DQoNCiMgRXhwZWN0ZWQgVmFyaWFuY2UgaW4gU2NvcmluZyBmb3IgVGVhbSBCIHZzLiBUZWFtIEENCnZhcnBvaW50c2IgPC0gZnVuY3Rpb24odGVhbWEsIHRlYW1iKXsNCiAgdmFyYiA8LSBlZmdhYih0ZWFtYSwgdGVhbWIpICogKGVlZmdvYih0ZWFtYSwgdGVhbWIpKigxIC0gZWVmZ29iKHRlYW1hLCB0ZWFtYikpKSAqIDINCiAgdmIgPC0gYXMubnVtZXJpYyh2YXJiKQ0KICByZXR1cm4odmIpDQp9DQoNCg0KIyBUaGlzIGZ1bmN0aW9uIHRha2VzIHRoZSBzY29yZXMgdGhhdCB3ZSBqdXN0IGZvdW5kIGZvciBUZWFtIEEgYW5kIFRlYW0gQiwgYW5kIGNvbmNhdGVuYXRlcyB0aGVtIHVzaW5nIHRoZSAiZ2x1ZSIgcGFja2FnZS4NCiMgV2UgY2FuIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIG5vdyBydW4gdGhyb3VnaCB0aGUgZW50aXJlIHRvdXJuYW1lbnQgcm91bmQgYnkgcm91bmQuIA0KbWF0Y2h1cCA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICBwYSA8LSByb3VuZChlcG9pbnRzYSh0ZWFtYSwgdGVhbWIpLCBkaWdpdHMgPSAyKQ0KICBwYiA8LSByb3VuZChlcG9pbnRzYih0ZWFtYSwgdGVhbWIpLCBkaWdpdHMgPSAyKQ0KICANCiAgdmEgPC0gdmFycG9pbnRzYSh0ZWFtYSwgdGVhbWIpDQogIHZiIDwtIHZhcnBvaW50c2IodGVhbWEsIHRlYW1iKQ0KICANCiAgIyBTaW5jZSB3ZSBrbm93IHRoZSBleHBlY3RlZCBzY29yZSBhbmQgdGhlIHZhcmlhbmNlLCB3ZSBjYW4gdXNlIHRob3NlIHRvIGZpbmQgd2luIHByb2JhYmlsaXRpZXMgZm9yIGVhY2ggdGVhbQ0KICB6IDwtIChwYSAtIHBiKSAvIHNxcnQodmEgKyB2YikNCiAgeiA8LSBhcy5udW1lcmljKHopDQogIA0KICAjIFVzaW5nIG91ciB6IHNjb3JlLCBmaW5kIHdpbiBwZXJjZW50YWdlIGEgYW5kIGINCiAgd3BhIDwtIHJvdW5kKHBub3JtKHopLCBkaWdpdHMgPSAzKQ0KICB3cGIgPC0gcm91bmQoMSAtIHBub3JtKHopLCBkaWdpdHMgPSAzKQ0KICANCiAgIyBEZWNsYXJlcyB0aGUgd2lubmVyIGJhc2VkIG9uIHRoZSBoaWdoZXIgd2luIHByb2JhYmlsaXR5DQogIGlmICh3cGEgPiB3cGIpew0KICAgIHdpbiA8LSB0ZWFtYQ0KICB9IGVsc2V7DQogICAgd2luIDwtIHRlYW1iDQogIH0NCiAgDQogICMgQ2FsY3VsYXRlcyB0aGUgZXhwZWN0ZWQgcG9pbnQgZGlmZmVyZW50aWFsDQogIGlmIChwYSA+IHBiKXsNCiAgICBwZCA8LSByb3VuZChwYSAtIHBiLCBkaWdpdHMgPSAyKQ0KICB9IGVsc2V7DQogICAgcGQgPC0gcm91bmQocGItcGEsIGRpZ2l0cyA9IDIpDQogIH0NCiAgDQogICMgVXNlcyB0aGUgImdsdWUiIHBhY2thZ2UgdG8gcHV0IGFsbCBvZiBvdXIgcmVzdWx0cyB0b2dldGhlciBpbnRvIGEgbmljZSBvdXRwdXQgYW5kIHByaW50cyBpdCBhZnRlcndhcmRzLg0KICBvdXQgPC0gZ2x1ZSgie3RlYW1hfSBFeHBlY3RlZCBzY29yZToge3BhfSwgDQogICAgICAgICAgICAgIHt0ZWFtYn0gRXhwZWN0ZWQgc2NvcmU6IHtwYn0sDQogICAgICAgICAgICAgIFByb2plY3RlZCBQb2ludCBEaWZmZXJlbnRpYWw6IHtwZH0NCiAgICAgICAgICAgICAgV2luIFByb2JhYmlsaXR5IGZvciB7dGVhbWF9OiB7d3BhfQ0KICAgICAgICAgICAgICBXaW4gUHJvYmFiaWxpdHkgZm9yIHt0ZWFtYn06IHt3cGJ9DQogICAgICAgICAgICAgIFByb2plY3RlZCB3aW5uZXI6IHt3aW59IikNCiAgDQogIG91dA0KfQ0KYGBgDQoNCjxicj4gDQoNCk5vdyB0aGF0IHdlIGhhdmUgb3VyIGZ1bmN0aW9ucywgd2UgY2FuIGVhc2lseSBydW4gdGhyb3VnaCBlYWNoIG1hdGNodXAgYW5kIHJlZHVjZSA2NyBiYXNrZXRiYWxsIGdhbWVzIHRvIGEgZmV3IGZ1bmN0aW9uIGNhbGxzLiANCg0KIyMgT3VyIFByZWRpY3Rpb25zey0udGFic2V0fQ0KIyMjIFJvdW5kIG9mIDY0IHstLnRhYnNldH0NCiMjIyMgVGhlIFNvdXRoIFJlZ2lvbiB7LX0NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQptYXRjaHVwKCJBdWJ1cm4iLCAiQWxhYmFtYSBTdC4iKQ0KDQptYXRjaHVwKCJMb3Vpc3ZpbGxlIiwgIkNyZWlnaHRvbiIpDQoNCm1hdGNodXAoIk1pY2hpZ2FuIiwgIlVDIFNhbiBEaWVnbyIpDQoNCm1hdGNodXAoIlRleGFzIEEmTSIsICJZYWxlIikNCg0KbWF0Y2h1cCgiT2xlIE1pc3MiLCAiTm9ydGggQ2Fyb2xpbmEiKQ0KDQptYXRjaHVwKCJJb3dhIFN0LiIsICJMaXBzY29tYiIpDQoNCm1hdGNodXAoIk1hcnF1ZXR0ZSIsICJOZXcgTWV4aWNvIikNCg0KbWF0Y2h1cCgiTWljaGlnYW4gU3QuIiwgIkJyeWFudCIpDQpgYGANCg0KIyMjIyBUaGUgV2VzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRmxvcmlkYSIsICJOb3Jmb2xrIFN0LiIpDQoNCm1hdGNodXAoIlVDb25uIiwgIk9rbGFob21hIikNCg0KbWF0Y2h1cCgiTWVtcGhpcyIsICJDb2xvcmFkbyBTdC4iKQ0KDQptYXRjaHVwKCJNYXJ5bGFuZCIsICJHcmFuZCBDYW55b24iKQ0KDQptYXRjaHVwKCJNaXNzb3VyaSIsICJEcmFrZSIpDQoNCm1hdGNodXAoIlRleGFzIFRlY2giLCAiVU5DVyIpDQoNCm1hdGNodXAoIkthbnNhcyIsICJBcmthbnNhcyIpDQoNCm1hdGNodXAoIlN0LiBKb2huJ3MgKE5ZKSIsICJPbWFoYSIpDQpgYGANCg0KIyMjIyBUaGUgRWFzdCBSZWdpb257LX0NCg0KYGBge3J9DQptYXRjaHVwKCJEdWtlIiwgIk1vdW50IFN0LiBNYXJ5J3MiKQ0KDQptYXRjaHVwKCJNaXNzaXNzaXBwaSBTdC4iLCAiQmF5bG9yIikNCg0KbWF0Y2h1cCgiT3JlZ29uIiwgIkxpYmVydHkiKQ0KDQptYXRjaHVwKCJBcml6b25hIiwgIkFrcm9uIikNCg0KbWF0Y2h1cCgiQllVIiwgIlZDVSIpDQoNCm1hdGNodXAoIldpc2NvbnNpbiIsICJNb250YW5hIikNCg0KbWF0Y2h1cCgiU2FpbnQgTWFyeSdzIChDQSkiLCAiVmFuZGVyYmlsdCIpDQoNCm1hdGNodXAoIkFsYWJhbWEiLCAiUm9iZXJ0IE1vcnJpcyIpDQpgYGANCg0KIyMjIyBUaGUgTWlkd2VzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiSG91c3RvbiIsICJTSVUgRWR3YXJkc3ZpbGxlIikNCg0KbWF0Y2h1cCgiR29uemFnYSIsICJHZW9yZ2lhIikNCg0KbWF0Y2h1cCgiQ2xlbXNvbiIsICJNY05lZXNlIikNCg0KbWF0Y2h1cCgiUHVyZHVlIiwgIkhpZ2ggUG9pbnQiKQ0KDQptYXRjaHVwKCJJbGxpbm9pcyIsICJYYXZpZXIiKQ0KDQptYXRjaHVwKCJLZW50dWNreSIsICJUcm95IikNCg0KbWF0Y2h1cCgiVUNMQSIsICJVdGFoIFN0LiIpDQoNCm1hdGNodXAoIlRlbm5lc3NlZSIsICJXb2Zmb3JkIikNCmBgYA0KDQojIyMjIFJlc3VsdHMgey19DQpTbywgaG93IGRpZCB3ZSBkbz8gTm90IGdvb2QgZW5vdWdoLCBpZiA2Ny82NyBpcyBvdXIgZXZlbnR1YWwgZ29hbC4gQnV0IGxldCdzIHRha2UgYSBsb29rIGF0IHdoYXQgZ2FtZXMgd2UgZ290IHdyb25nIGFuZCBrZWVwIGEgcnVubmluZyB0YWxseSAgaW4gdGhlICpSZXN1bHRzKiB0YWIgc28gdGhhdCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhvc2UgdGVhbXMgYWZ0ZXJ3YXJkcy4NCg0KVGhlIGdhbWVzIHdlIGdvdCB3cm9uZyBhbmQgdGhlaXIgcmVzcGVjdGl2ZSBXaW4gUHJvYmFiaWxpdGllczoNCg0KKiAqKiM4KiogTG91aXN2aWxsZSAoNjQuNyUpIHZzICoqIzkqKiBDcmVpZ2h0b24gKDM1LjMlKQ0KDQoqICoqIzcqKiBNYXJxdWV0dGUgKDYzLjglKSB2cyAqKiMxMCoqIE5ldyBNZXhpY28gKDM2LjIlKQ0KDQoqICoqIzYqKiBNaXNzb3VyaSAoNzguOCUpIHZzICoqIzExKiogRHJha2UgKDIxLjIlKQ0KDQoqICoqIzcqKiBLYW5zYXMgKDY4LjQlKSB2cyAqKiMxMCoqIEFya2Fuc2FzICgzMS42JSkNCg0KKiAqKiM1KiogQ2xlbXNvbiAoODAuOCUpIHZzICoqIzEyKiogTWNOZWVzZSAoMTkuMiUpDQoNCiMjIyBSb3VuZCBvZiAzMiB7LS50YWJzZXR9DQojIyMjIFRoZSBTb3V0aCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiQXVidXJuIiwgIkNyZWlnaHRvbiIpDQoNCm1hdGNodXAoIk1pY2hpZ2FuIiwgIlRleGFzIEEmTSIpDQoNCm1hdGNodXAoIk9sZSBNaXNzIiwgIklvd2EgU3QuIikNCg0KbWF0Y2h1cCgiTmV3IE1leGljbyIsICJNaWNoaWdhbiBTdC4iKQ0KYGBgDQoNCiMjIyMgVGhlIFdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkZsb3JpZGEiLCAiVUNvbm4iKQ0KDQptYXRjaHVwKCJDb2xvcmFkbyBTdC4iLCAiTWFyeWxhbmQiKQ0KDQptYXRjaHVwKCJEcmFrZSIsICJUZXhhcyBUZWNoIikNCg0KbWF0Y2h1cCgiQXJrYW5zYXMiLCAiU3QuIEpvaG4ncyAoTlkpIikNCmBgYA0KDQojIyMjIFRoZSBFYXN0IFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJEdWtlIiwgIkJheWxvciIpDQoNCm1hdGNodXAoIk9yZWdvbiIsICJBcml6b25hIikNCg0KbWF0Y2h1cCgiQllVIiwgIldpc2NvbnNpbiIpDQoNCm1hdGNodXAoIlNhaW50IE1hcnkncyAoQ0EpIiwgIkFsYWJhbWEiKQ0KYGBgDQoNCiMjIyMgVGhlIE1pZHdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkhvdXN0b24iLCAiR29uemFnYSIpDQoNCm1hdGNodXAoIk1jTmVlc2UiLCAiUHVyZHVlIikNCg0KbWF0Y2h1cCgiSWxsaW5vaXMiLCAiS2VudHVja3kiKQ0KDQptYXRjaHVwKCJVQ0xBIiwgIlRlbm5lc3NlZSIpDQpgYGANCg0KIyMjIyBSZXN1bHRzIHstfQ0KDQpUaGUgZ2FtZXMgd2UgZ290IHdyb25nIGFuZCB0aGVpciByZXNwZWN0aXZlIFdpbiBQcm9iYWJpbGl0aWVzOg0KDQoqICoqIzUqKiBNaWNoaWdhbiAoNDMuMiUpIHZzICoqIzQqKiBUZXhhcyBBJk0gKDU2LjglKQ0KDQoqICoqIzYqKiBPbGUgTWlzcyAoMzIuNyUpIHZzICoqIzMqKiBJb3dhIFN0LiAoNjcuMyUpDQoNCiogKiojMTAqKiBBcmthbnNhcyAoMjEuMiUpIHZzICoqIzIqKiBTdC4gSm9obidzICg3OC44JSkNCg0KKiAqKiM2KiogQllVICgzNC45JSkgdnMgKiojMyoqIFdpc2NvbnNpbiAoNjUuMSUpDQoNCiMjIyBTd2VldCBTaXh0ZWVuIHstLnRhYnNldH0NCiMjIyMgVGhlIFNvdXRoIFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJBdWJ1cm4iLCAiTWljaGlnYW4iKQ0KDQptYXRjaHVwKCJPbGUgTWlzcyIsICJNaWNoaWdhbiBTdC4iKQ0KYGBgDQoNCiMjIyMgVGhlIFdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkZsb3JpZGEiLCAiTWFyeWxhbmQiKQ0KDQptYXRjaHVwKCJUZXhhcyBUZWNoIiwgIkFya2Fuc2FzIikNCmBgYA0KDQojIyMjIFRoZSBFYXN0IFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJEdWtlIiwgIkFyaXpvbmEiKQ0KDQptYXRjaHVwKCJCWVUiLCAiQWxhYmFtYSIpDQpgYGANCg0KIyMjIyBUaGUgTWlkd2VzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiSG91c3RvbiIsICJQdXJkdWUiKQ0KDQptYXRjaHVwKCJLZW50dWNreSIsICJUZW5uZXNzZWUiKQ0KYGBgDQoNCiMjIyMgUmVzdWx0cyB7LX0NCg0KVGhlIGdhbWVzIHdlIGdvdCB3cm9uZyBhbmQgdGhlaXIgcmVzcGVjdGl2ZSBXaW4gUHJvYmFiaWxpdGllczoNCg0KKiAqKk5vbmUqKg0KDQojIyMgRWxpdGUgRWlnaHQgey0udGFic2V0fQ0KIyMjIyBUaGUgU291dGggUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkF1YnVybiIsICJNaWNoaWdhbiBTdC4iKQ0KYGBgDQoNCiMjIyMgVGhlIFdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkZsb3JpZGEiLCAiVGV4YXMgVGVjaCIpDQpgYGANCg0KIyMjIyBUaGUgRWFzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRHVrZSIsICJBbGFiYW1hIikNCmBgYA0KDQojIyMjIFRoZSBNaWR3ZXN0IFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJIb3VzdG9uIiwgIlRlbm5lc3NlZSIpDQpgYGANCg0KIyMjIyBSZXN1bHRzIHstfQ0KDQpUaGUgZ2FtZXMgd2UgZ290IHdyb25nIGFuZCB0aGVpciByZXNwZWN0aXZlIFdpbiBQcm9iYWJpbGl0aWVzOg0KDQoqICoqTm9uZSoqDQoNCiMjIyBGaW5hbCBGb3VyIHstLnRhYnNldH0NCiMjIyMgU291dGgvV2VzdCB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJBdWJ1cm4iLCAiRmxvcmlkYSIpDQpgYGANCg0KIyMjIyBFYXN0L01pZHdlc3Qgey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRHVrZSIsICJIb3VzdG9uIikNCmBgYA0KDQojIyMjIFJlc3VsdHMgey19DQoNClRoZSBnYW1lIHdlIGdvdCB3cm9uZyBhbmQgaXRzIHJlc3BlY3RpdmUgV2luIFByb2JhYmlsaXR5Og0KDQoqICoqIzEqKiBEdWtlICg1NS42JSkgdnMgKiojMSoqIEhvdXN0b24gKDQ0LjQlKQ0KDQojIyMgTmF0aW9uYWwgQ2hhbXBpb25zaGlwIHstfQ0KDQpZb3UgbWF5IGhhdmUgbm90aWNlZCBieSBub3cgdGhhdCBlYWNoIHJvdW5kLCBJIGFtIHJlcGxhY2luZyB0aGUgcmVzdWx0cyB0aGF0IHdlIHByZWRpY3RlZCB3aXRoIHRoZSByZWFsLWxpZmUgb3V0Y29tZXMuIFVwIHRvIHRoaXMgcG9pbnQgaXQgd291bGRuJ3QgaGF2ZSBtYWRlIGEgZGlmZmVyZW5jZSBvdXRzaWRlIG9mIG9uZSBnYW1lLCAqKiMxMCoqIEFya2Fuc2FzIHZzICoqIzIqKiBTdC4gSm9obidzLiBFdmVyeSBvdGhlciB0ZWFtIHdlIGluY29ycmVjdGx5IGd1ZXNzZWQgd291bGQgbG9zZSwgYmVzaWRlcyBBcmthbnNhcywgd2VudCBvbiB0byBsb3NlIGluIHRoZSBuZXh0IHJvdW5kIGFuZCBkaWRuJ3QgY2hhbmdlIHRoZSBvdXRjb21lIG9mIHRoZSBTd2VldCBTaXh0ZWVuIGFuZCBFbGl0ZSBFaWdodC4gSG91c3RvbiwgaXJvbmljYWxseSwgaXMgbm90IGFuIGV4Y2VwdGlvbiB0byB0aGlzIHJ1bGUsIGRlc3BpdGUgb3VyIHByZWRpY3Rpb24gZ2l2aW5nIHRoZW0gYSBzbGlnaHQgZWRnZSBpbiB0aGlzIGZpbmFsLCBpbmNvcnJlY3QsIHJlc3VsdC4gSW4gcmVhbGl0eSwgRmxvcmlkYSBkZWZlYXRlZCBIb3VzdG9uIDY1LTYzIHRvIGNsYWltIHRoZSBOYXRpb25hbCBUaXRsZS4gDQoNCklmIHRoaXMgd2VyZSBuZXh0IHllYXIncyBicmFja2V0IGFuZCB3ZSBkaWRuJ3Qga25vdyBhbGwgb2YgdGhlIG91dGNvbWVzIHlldCwgaW5jb3JyZWN0bHkgZ3Vlc3NpbmcgdGhlIHdpbm5lciBvZiBib3RoIGEgRmluYWwgRm91ciBnYW1lICphbmQqIHRoZSBDaGFtcGlvbnNoaXAgd291bGQgYmUgYW4gaW5jcmVkaWJseSBwb29yIHdheSB0byBsb3NlIGEgcGVyZmVjdCBicmFja2V0LiBCdXQgdGhpcyBoaWdobGlnaHRzIGEgY29uY2VwdCB0aGF0IEknbGwgdG91Y2ggb24gbGF0ZXIgZGVzcGl0ZSBub3QgZnVsbHkgdW5kZXJzdGFuZGluZy4gQXMgdGhlIGZpZWxkIG5hcnJvd3MgYW5kIHRoZSBsZXZlbCBvZiBwbGF5IGluY3JlYXNlcywgb3VyIHByZWRpY3Rpb25zLCBpbiB0aGVvcnksIHNob3VsZCBiZSB3b3JzZS4gDQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRmxvcmlkYSIsICJIb3VzdG9uIikNCmBgYA0KDQpUaGUgZ2FtZSB3ZSBnb3Qgd3JvbmcgYW5kIGl0cyByZXNwZWN0aXZlIFdpbiBQcm9iYWJpbGl0eTogDQoNCiogKiojMSoqIEZsb3JpZGEgKDQ3LjIlKSB2cyAqKiMxKiogSG91c3RvbiAoNTIuOCUpDQoNCiMgVGhlIFJlc3VsdHMNCg0KQmVmb3JlIHdlIGdldCBpbnRvIGdyYXBoaW5nIHRoZXNlIHRlYW1zIGFuZCB0cnlpbmcgdG8gY29tZSB1cCB3aXRoIHNvbWUgY2x1ZXMgdGhhdCBtYXkgaGF2ZSBwcmV2ZW50ZWQgb3VyIGJyYWNrZXQgZnJvbSBidXN0aW5nIG9uIHRoZSB2ZXJ5IGZpcnN0IGdhbWUgb2YgdGhlIFJvdW5kIG9mIDY0IChMb3Vpc3ZpbGxlIHZzIENyZWlnaHRvbiksIGxldCdzIGp1c3QgdGFrZSBhIGxvb2sgYXQgYWxsIG9mIHRoZSBtYXRjaHVwcyB3ZSBnb3QgaW5jb3JyZWN0bHkgaW4gb25lIHBsYWNlLiBPZiBteSA1Ni82NyByZXN1bHRzLCBoZXJlIGFyZSBhbGwgMTEgaW5jb3JyZWN0IHByZWRpY3Rpb25zLiANCg0KX19Sb3VuZCBvZiA2NF9fDQoNCiogKiojOCoqIExvdWlzdmlsbGUgKDY0LjclKSB2cyAqKiM5KiogQ3JlaWdodG9uICgzNS4zJSkNCg0KKiAqKiM3KiogTWFycXVldHRlICg2My44JSkgdnMgKiojMTAqKiBOZXcgTWV4aWNvICgzNi4yJSkNCg0KKiAqKiM2KiogTWlzc291cmkgKDc4LjglKSB2cyAqKiMxMSoqIERyYWtlICgyMS4yJSkNCg0KKiAqKiM3KiogS2Fuc2FzICg2OC40JSkgdnMgKiojMTAqKiBBcmthbnNhcyAoMzEuNiUpDQoNCiogKiojNSoqIENsZW1zb24gKDgwLjglKSB2cyAqKiMxMioqIE1jTmVlc2UgKDE5LjIlKQ0KDQpfX1JvdW5kIG9mIDMyX18NCg0KKiAqKiM1KiogTWljaGlnYW4gKDQzLjIlKSB2cyAqKiM0KiogVGV4YXMgQSZNICg1Ni44JSkNCg0KKiAqKiM2KiogT2xlIE1pc3MgKDMyLjclKSB2cyAqKiMzKiogSW93YSBTdC4gKDY3LjMlKQ0KDQoqICoqIzEwKiogQXJrYW5zYXMgKDIxLjIlKSB2cyAqKiMyKiogU3QuIEpvaG4ncyAoNzguOCUpDQoNCiogKiojNioqIEJZVSAoMzQuOSUpIHZzICoqIzMqKiBXaXNjb25zaW4gKDY1LjElKQ0KDQpfX0ZpbmFsIEZvdXJfXw0KDQoqICoqIzEqKiBEdWtlICg1NS42JSkgdnMgKiojMSoqIEhvdXN0b24gKDQ0LjQlKQ0KDQpfX05hdGlvbmFsIENoYW1waW9uc2hpcF9fDQoNCiogKiojMSoqIEZsb3JpZGEgKDQ3LjIlKSB2cyAqKiMxKiogSG91c3RvbiAoNTIuOCUpDQoNCjxicj4NCg0KV2UgY2FuIHNlZSB0aGF0IGFzIHdlIGdldCBjbG9zZXIgdG8gdGhlIENoYW1waW9uc2hpcCwgYW5kIHRoZW4gaW4gdGhlIENoYW1waW9uc2hpcCBpdHNlbGYsIHRoZSBsZXZlbCBvZiBjb21wZXRpdGlvbiBnZXRzIG11Y2ggbW9yZSBldmVuLiBPdXIgd2luIHByb2JhYmlsaXRpZXMgYW1vdW50IHRvIGVzc2VudGlhbGx5IGEgY29pbiBmbGlwLCBlc3BlY2lhbGx5IHdoZW4gY29uc2lkZXJpbmcgdGhhdCB0aGUgKnNjb3Jlcyogb2YgZWFjaCBnYW1lIGFmdGVyIHRoZSBFbGl0ZSBFaWdodCBpcyBwcmVkaWN0ZWQgdG8gYmUgd2l0aGluIDEgcG9pbnQuIE5vbmUgb2YgdGhlIGdhbWVzIGFjdHVhbGx5IGVuZGVkIGluIHN1Y2ggYSBuYXJyb3cgbWFyZ2luLCBidXQgYm90aCBvZiB0aGUgZ2FtZXMgdGhhdCB3ZSBwcmVkaWN0ZWQgaW5jb3JyZWN0bHkgKndlcmUqIGRlY2lkZWQgYnkgb25lIHBvc3Nlc3Npb24uIFRoZSBvbmx5IGdhbWUgd2UgZ290IGNvcnJlY3QgKEF1YnVybiB2cyBGbG9yaWRhKSB3YXMgZGVjaWRlZCBieSA2IHBvaW50cywgb3IganVzdCB0d28gcG9zc2Vzc2lvbnMuDQoNCkdldHRpbmcgYWxsIG9mIHRoZSBTd2VldCBTaXh0ZWVuIGFuZCBFbGl0ZSBFaWdodCBnYW1lcyBjb3JyZWN0IGFzIHRoZSBjb21wZXRpdGlvbiBuYXJyb3dzIGlzIGEgcmVzdWx0IEknbSBjb250ZW50IHdpdGgsIGJ1dCBkb2Vzbid0IHNlcnZlIHVzIHRvbyBtdWNoIHVzZWZ1bCBpbmZvcm1hdGlvbi4gSW4gZmFjdCwgb3V0IG9mIGFsbCB0d2VsdmUgZ2FtZXMgcGxheWVkIGluIHRob3NlIHJvdW5kcyB0aGF0IHdlIGdvdCBjb3JyZWN0LCBvbmx5IHRocmVlIG9mIHRoZW0gZW5kZWQgd2l0aGluIG9uZSBwb3NzZXNzaW9uLiBSZWFsaXN0aWNhbGx5LCB0aGVyZSdzIGFuIGVsZW1lbnQgb2YgbHVjayB3aGVuIGl0IGNvbWVzIHRvIGRlY2lkaW5nIHdoaWNoIHRlYW0gd2lsbCB3aW4gdGhlc2UgY29pbiBmbGlwIGdhbWVzIGlmIHdlIGdvIHN0cmljdGx5IGJ5IHRoZSBzY29yZSBwcmVkaWN0aW9ucywgYW5kIG5vdCBzb21lIG90aGVyIG1ldHJpYy4gDQoNCk9uIHRoZSBvdGhlciBlbmQgb2YgdGhlIHNwZWN0cnVtLCBhcmUgdGhlIHRydWUgdXBzZXRzIC0gdGhlIGJlZ2lubmluZ3Mgb2YgYSBDaW5kZXJlbGxhIFN0b3J5LiBXaGlsZSAyMDI1J3MgYnJhY2tldCBmZWF0dXJlZCByZWxhdGl2ZWx5IGxpdHRsZSBjaGFvcywgdGhlcmUgYXJlIHR3byB0ZWFtcyB0aGF0IHN0YW5kIG91dCBmcm9tIHRoZSBjcm93ZCBpbiBvdXIgZ3JvdXAgb2YgaW5jb3JyZWN0IHByZWRpY3Rpb25zIGFib3ZlLiBUaGUgZmlyc3QsIHdobyBoYXMgYmVlbiBtZW50aW9uZWQgb24gbW9yZSB0aGFuIG9uZSBvY2Nhc2lvbiBhbHJlYWR5LCB0aGUgKipBcmthbnNhcyBSYXpvcmJhY2tzKiouIFRoZSBvbmx5IGRvdWJsZS1kaWdpdCBzZWVkIHRvIG1ha2UgaXQgdG8gdGhlIFN3ZWV0IFNpeHRlZW4gd2l0aCByZWxhdGl2ZWx5IG1vZGVzdCwgYnV0IHJlc3BlY3RhYmxlIHN0YXRzLCB0aGUgUmF6b3JiYWNrcyB3ZXJlbid0IG5lY2Vzc2FyaWx5IGEgcHJvdG90eXBpY2FsIENpbmRlcmVsbGEgdGVhbS4gQnkgdmlydHVlIG9mIHBsYXlpbmcgaW4gdGhlIFNFQywgd2hpY2ggbWFueSBjb25zaWRlcmVkIHRvIGJlIHRoZSBzdHJvbmdlc3QgY29uZmVyZW5jZSBpbiB0aGUgbmF0aW9uIGxhc3QgeWVhciwgdGhleSBjYXJyaWVkIGEgbG90IG1vcmUgdGFsZW50IHRoYW4gdGhlaXIgc2VlZGluZyBtaWdodCBzdWdnZXN0LiBIb3dldmVyLCB3ZSB3ZXJlIHN0aWxsIHVuYWJsZSB0byBwcmVkaWN0IGVpdGhlciBvZiB0aGVpciB1cHNldCB3aW5zIGNvcnJlY3RseS4NCg0KVGhlIG90aGVyIG5vdGFibGUgdGVhbSwgb3duZXJzIG9mIHRoZSBsYXJnZXN0IHVwc2V0IHZpY3RvcnkgdGhyb3VnaG91dCB0aGUgZW50aXJlIHRvdXJuYW1lbnQgLSB0aGUgKipNY05lZXNlIENvd2JveXMqKi4gVGhpcyByZXN1bHQgaGl0cyBwYXJ0aWN1bGFybHkgY2xvc2UgdG8gaG9tZSwgYXMgaXQgY2FtZSBhdCB0aGUgY29uc2VxdWVuY2Ugb2YgYW4gZWFybHkgZXhpdCBmb3IgbXkgb3duIENsZW1zb24gVGlnZXJzLiBJIHdpbGwgcmVmcmFpbiBmcm9tIG1ha2luZyBhbnkgYmlhc2VkIGNvbW1lbnRzIG9yIGFzc3VtcHRpb25zIGFib3V0IHRoZSBvdXRjb21lIG9mIHRoYXQgZ2FtZSB0aGF0IGNhbid0IGJlIHZlcmlmaWVkIGJ5IHRoZSBkYXRhIEkgaGF2ZSBpbiBmcm9udCBvZiBtZSwgYW5kIHdpbGwgaW5zdGVhZCBvcHQgdG8gY3JlZGl0IHRoZSB1bmV4cGVjdGVkIGxvc3MgdG8gYW4gaW5qdXJ5IHN1ZmZlcmVkIGJ5IENsZW1zb24gZ3VhcmQgRGlsbG9uIEh1bnRlciBkdXJpbmcgdGhlIEFDQyBUb3VybmFtZW50Lg0KDQpUaGUgcmVzdCBvZiB0aGUgaW5jb3JyZWN0IGd1ZXNzZXMgdGVuZCB0byBmYWxsIGluIHRoZSByYW5nZSBvZiBhcm91bmQgYSAzMC00NSUgd2luIHByb2JhYmlsaXR5IHBlcmNlbnRhZ2UgZm9yIHRoZSB1bmRlcmRvZ3MuIFRoZXNlIGFyZSByZXN1bHRzIHRoYXQgbGlrZWx5IGNvdWxkIGhhdmUgZ29uZSBlaXRoZXIgd2F5LCBidXQgd2l0aG91dCBpbnZlc3RpZ2F0aW5nIHRoZW0gZnVydGhlciB3ZSdyZSBsZWZ0IHZpY3RpbXMgb2YgY2hhbmNlLiBJbiBvcmRlciB0byB0cnkgYW5kIGdhcm5lciBzb21lIGluc2lnaHQsIEknbGwgZXhwbG9yZSBzb21lIG9mIHRoZSBzdGF0aXN0aWNzIHdlIGhhdmUgYXQgb3VyIGRpc3Bvc2FsIHRvIHNlZSBpZiB0aGVyZSdzIGEgZGlzY3JlcGFuY3kgYmV0d2VlbiBvdXIgIkNpbmRlcmVsbGFzIiBhbmQgb3VyIHByb3ZlcmJpYWwgInN0ZXBzaXN0ZXJzLiINCg0KIyBUaGUgR2xhc3MgU2xpcHBlciAtIFdoYXQgU2V0cyBUZWFtcyBBcGFydD8NCg0KV2UnbGwgZmlyc3Qgc3RhcnQgYnkgY3JlYXRpbmcgYSBzdWJzZXQgb2YgdGhlIHRlYW1zIHRoYXQgcHVsbGVkIG9mZiBhbiAidXBzZXQiIGdpdmVuIG91ciBwcmVkaWN0aW9ucywgYW5kIGEgc2VwYXJhdGUgc3Vic2V0IG9mIHRoZSB0ZWFtcyB3aG8gbG9zdCB0byB0aGVtLiBUaGF0IHdheSwgd2UgY2FuIGhpZ2hsaWdodCBlYWNoIGFuZCBzZWUgaWYgdGhlcmUncyBhbnkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdHdvIGdyb3Vwcy4NCg0KPGJyPg0KDQpgYGB7ciwgZmlnLnNob3c9J2hvbGQnLCBvdXQud2lkdGg9IjUwJSIsIHdhcm5pbmc9RkFMU0V9DQojIEZpbHRlcnMgb3V0IGp1c3Qgb3VyICJ1bmRlcmRvZ3MiDQp1bmRlcnMgPC0gc3RhdHMyIHw+DQogIGZpbHRlcih0ZWFtICVpbiUgYygiQ3JlaWdodG9uIiwgIk5ldyBNZXhpY28iLCAiRHJha2UiLCAiQXJrYW5zYXMiLCAiTWNOZWVzZSIsICJNaWNoaWdhbiIsICJPbGUgTWlzcyIsICJCWVUiLCAiSG91c3RvbiIsICJGbG9yaWRhIikpDQoNCiMgRmlsdGVycyBvdXQganVzdCB0aGUgdGVhbXMgb3VyICJ1bmRlcmRvZ3MiIGxvc3QgdG8NCnVwc2V0cyA8LSBzdGF0czIgfD4NCiAgZmlsdGVyKHRlYW0gJWluJSBjKCJMb3Vpc3ZpbGxlIiwgIk1hcnF1ZXR0ZSIsICJNaXNzb3VyaSIsICJLYW5zYXMiLCAiQ2xlbXNvbiIsICJUZXhhcyBBJk0iLCAiSW93YSBTdC4iLCAiU3QuIEpvaG4ncyAoTlkpIiwgIldpc2NvbnNpbiIsICJEdWtlIiwgIkhvdXN0b24iKSkNCg0KZ2dwbG90KHN0YXRzMiwgYWVzKHggPSBlRkcsIHkgPSBvcHAuZUZHKSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oc3RhdHMyJGVGRyksIGNvbG9yID0gImJsYWNrIikrDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1lYW4oc3RhdHMyJG9wcC5lRkcpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2NiYl90ZWFtcyhkYXRhID0gc3RhdHMyLCBhZXModGVhbSA9IHRlYW0pLCB3aWR0aCA9IDAuMDUsIHNob3cubGVnZW5kID0gRkFMU0UpKw0KICBnZ2hpZ2hsaWdodCh0ZWFtICVpbiUgYygiQ3JlaWdodG9uIiwgIk5ldyBNZXhpY28iLCAiRHJha2UiLCAiQXJrYW5zYXMiLCAiTWNOZWVzZSIsICJNaWNoaWdhbiIsICJPbGUgTWlzcyIsICJCWVUiLCAiSG91c3RvbiIsICJGbG9yaWRhIikpKw0KICB4bGltKG1pbihzdGF0czIkZUZHKSwgbWF4KHN0YXRzMiRlRkcpKSsNCiAgeWxpbShtaW4oc3RhdHMyJG9wcC5lRkcpLCBtYXgoc3RhdHMyJG9wcC5lRkcpKSsNCiAgbGFicyh4ID0gIlRlYW0gZUZHJSIsDQogICAgICAgeSA9ICJPcHBvbmVudCBlRkclIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIGVGRyUgdnMuIE9wcG9uZW50IGVGRyUgZm9yICJVbmRlcmRvZyIgVGVhbXMnKQ0KDQpnZ3Bsb3Qoc3RhdHMyLCBhZXMoeCA9IGVGRywgeSA9IG9wcC5lRkcpKSsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkZUZHKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkb3BwLmVGRyksIGNvbG9yID0gImJsYWNrIikrDQogIGdlb21fY2JiX3RlYW1zKGRhdGEgPSBzdGF0czIsIGFlcyh0ZWFtID0gdGVhbSksIHdpZHRoPTAuMDUsIHNob3cubGVnZW5kID0gRkFMU0UpKw0KICBnZ2hpZ2hsaWdodCh0ZWFtICVpbiUgYygiTG91aXN2aWxsZSIsICJNYXJxdWV0dGUiLCAiTWlzc291cmkiLCAiS2Fuc2FzIiwgIkNsZW1zb24iLCAiVGV4YXMgQSZNIiwgIklvd2EgU3QuIiwgIlN0LiBKb2huJ3MgKE5ZKSIsICJXaXNjb25zaW4iLCAiRHVrZSIsICJIb3VzdG9uIikpKw0KICB4bGltKG1pbihzdGF0czIkZUZHKSwgbWF4KHN0YXRzMiRlRkcpKSsNCiAgeWxpbShtaW4oc3RhdHMyJG9wcC5lRkcpLCBtYXgoc3RhdHMyJG9wcC5lRkcpKSsNCiAgbGFicyh4ID0gIlRlYW0gZUZHJSIsDQogICAgICAgeSA9ICJPcHBvbmVudCBlRkclIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIGVGRyUgdnMuIE9wcG9uZW50IGVGRyUgZm9yIFRlYW1zIFdobyBXZXJlICJVcHNldCInKQ0KYGBgDQoNCjxicj4NCg0KSGVyZSB3ZSBnZXQgc29tZSBzbGlnaHQgaW5zaWdodCBhcyB0byB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGEgZmV3IG9mIHRoZXNlIHRlYW1zLCBidXQgZm9yIHRoZSBtb3N0IHBhcnQgdGhlIHJlc3VsdHMgYXJlIGluY29uY2x1c2l2ZS4gSW4gdGhpcyBwYXJ0aWN1bGFyIGdyYXBoLCB5b3Ugd2FudCB0byBiZSBpbiB0aGUgYm90dG9tIHJpZ2h0IHF1YWRyYW50IHdpdGggYSBoaWdoIGBlRkclYCwgYW5kIGEgbG93IGBvcHAuZUZHJWAuICBXZSBjYW4gc2VlIHRoYXQgdGVhbXMgbGlrZSAqKk1jTmVlc2UqKiwgKipDcmVpZ2h0b24qKiwgYW5kICoqTWljaGlnYW4qKiBmYXJlIGJldHRlciBpbiBib3RoIGBlRkclYCBhbmQgYG9wcC5lRkclYCB0aGFuIHRoZWlyIG9wcG9uZW50cywgYnV0IG1vcmUgb2Z0ZW4gdGhhbiBub3QgdGhlIHBhdHRlcm4gZG9lc24ndCBzZWVtIHRvIGhvbGQuIEl0J3Mgc3RpbGwgd29ydGggbm90aW5nIHRoYXQgc2l4IG9mIHRoZSB0ZWFtcyB3aG8gc3VmZmVyZWQgdXBzZXQgbG9zc2VzIGhhZCBhIGJlbG93IGF2ZXJhZ2UgYGVGRyVgLCBhbmQgQ2xlbXNvbiBpcyBqdXN0IHNpZ2h0bHkgYWJvdmUgYXZlcmFnZS4NCg0KPGJyPg0KDQpTaW5jZSBgZUZHJWAgYW5kIGBvcHAuZUZHJWAgYXJlbid0IG9wcG9uZW50LWFkanVzdGVkLCB3ZSBjYW4gdHJ5IHRvIGNvbXBhcmUgb3VyIG9wcG9uZW50LWFkanVzdGVkIGVmZmljaWVuY2llcyBhbmQgc2VlIGlmIHRoYXQgZ2l2ZXMgdXMgc29tZSBtb3JlIGluc2lnaHQuIEV2ZW4gdGhvdWdoIHRoaXMgZm9sbG93cyBvdXIgbWV0aG9kb2xvZ3kgZm9yIGZpbmRpbmcgb3VyIGV4cGVjdGVkIHNjb3JlcywgYW5kIGxpa2VseSB3b24ndCB0ZWxsIHVzIG11Y2gsIG9uZSBvciB0d28gb3V0bGllcnMgY291bGQgYmUgdGhlIGRpZmZlcmVuY2UgbWFrZXIgd2hlbiBkZWNpZGluZyB3aGljaCBvdGhlcndpc2UgZXZlbmx5LW1hdGNoZWQgdGVhbSB3ZSBzaG91bGQgcGljay4NCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgb3V0LndpZHRoPSI1MCUiLCB3YXJuaW5nPUZBTFNFfQ0KZ2dwbG90KHN0YXRzMiwgYWVzKHggPSBPUnRnLCB5ID0gRFJ0ZykpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiRPUnRnKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkRFJ0ZyksIGNvbG9yID0gImJsYWNrIikrDQogIGdlb21fY2JiX3RlYW1zKGRhdGEgPSBzdGF0czIsIGFlcyh0ZWFtID0gdGVhbSksIHdpZHRoPTAuMDUsIHNob3cubGVnZW5kID0gRkFMU0UpKw0KICBnZ2hpZ2hsaWdodCh0ZWFtICVpbiUgYygiQ3JlaWdodG9uIiwgIk5ldyBNZXhpY28iLCAiRHJha2UiLCAiQXJrYW5zYXMiLCAiTWNOZWVzZSIsICJNaWNoaWdhbiIsICJPbGUgTWlzcyIsICJCWVUiLCAiSG91c3RvbiIsICJGbG9yaWRhIikpKw0KICB4bGltKG1pbihzdGF0czIkT1J0ZyksIG1heChzdGF0czIkT1J0ZykpKw0KICB5bGltKG1pbihzdGF0czIkRFJ0ZyksIG1heChzdGF0czIkRFJ0ZykpKw0KICBsYWJzKHggPSAiVGVhbSBPUnRnIiwNCiAgICAgICB5ID0gIlRlYW0gRFJ0ZyIsDQogICAgICAgdGl0bGUgPSAnVGVhbSBPUnRnIHZzLiBUZWFtIERSdGcgZm9yICJVbmRlcmRvZyIgVGVhbXMnKQ0KDQpnZ3Bsb3Qoc3RhdHMyLCBhZXMoeCA9IE9SdGcsIHkgPSBEUnRnKSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oc3RhdHMyJE9SdGcpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiREUnRnKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9jYmJfdGVhbXMoZGF0YSA9IHN0YXRzMiwgYWVzKHRlYW0gPSB0ZWFtKSwgd2lkdGg9MC4wNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrDQogIGdnaGlnaGxpZ2h0KHRlYW0gJWluJSBjKCJMb3Vpc3ZpbGxlIiwgIk1hcnF1ZXR0ZSIsICJNaXNzb3VyaSIsICJLYW5zYXMiLCAiQ2xlbXNvbiIsICJUZXhhcyBBJk0iLCAiSW93YSBTdC4iLCAiU3QuIEpvaG4ncyAoTlkpIiwgIldpc2NvbnNpbiIsICJEdWtlIiwgIkhvdXN0b24iKSkrDQogIHhsaW0obWluKHN0YXRzMiRPUnRnKSwgbWF4KHN0YXRzMiRPUnRnKSkrDQogIHlsaW0obWluKHN0YXRzMiREUnRnKSwgbWF4KHN0YXRzMiREUnRnKSkrDQogIGxhYnMoeCA9ICJUZWFtIE9SdGciLA0KICAgICAgIHkgPSAiVGVhbSBEUnRnIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIE9SdGcgdnMuIFRlYW0gRFJ0ZyBmb3IgVGVhbXMgV2hvIFdlcmUgIlVwc2V0IicpDQpgYGANCg0KPGJyPg0KDQpBcyBleHBlY3RlZCwgdGhpcyBncmFwaCBkb2Vzbid0IHRlbGwgdXMgYWxsIHRvbyBtdWNoIGVpdGhlci4gVGhlIG9ubHkgcmVhbCBpbnNpZ2h0IGhlcmUgbWlnaHQgYmUgdGhhdCBnaXZlbiB0aGUgY2x1c3RlcmluZyBvZiB0aGUgdGVhbXMgd2hvIGZhY2VkIHVwc2V0cywgdGhlIG9uZXMgd2hvIGxvc3QgaW4gdGhlIFJvdW5kIG9mIDY0IGFuZCBSb3VuZCBvZiAzMiBkb24ndCBkbyBhbnl0aGluZyBleGNlcHRpb25hbGx5IHdlbGwuIFRoZXkncmUgYWJvdmUgYXZlcmFnZSBpbiBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSBlZmZpY2llbmN5LCBidXQgdGhleSBhcmVuJ3QgaW1tdW5lIHRvIGxvc2luZyBhIGJhc2tldGJhbGwgZ2FtZS4gVGhlIG90aGVyIHRlYW1zIGFsbCB0aGUgd2F5IG91dCBvbiB0aGUgcmlnaHQgZW5kIG9mIHRoZSBncmFwaCB3aXRoIER1a2UgaW4gYE9SdGdgIGFyZSBGbG9yaWRhLCB3aG8gd291bGQgZXZlbnR1YWxseSBnbyBvbiB0byB3aW4gdGhlIFRvdXJuYW1lbnQsIGFuZCBBdWJ1cm4sIHdobyBsb3N0IHRvIEZsb3JpZGEgaW4gdGhlIEZpbmFsIEZvdXIuIA0KDQpUaGUgdGVhbSBjbG9zZXN0IHRvIEhvdXN0b24gb24gdGhpcyBncmFwaD8gVGVubmVzc2VlLiBXaG8gdGhleSBkZWZlYXRlZCBpbiB0aGUgRWxpdGUgRWlnaHQuIEkgdGhpbmsgaXQncyBub3QgdW5yZWFzb25hYmxlIHRvIHNheSB0aGF0ICp0aGVzZSogdGVhbXMgKmFyZSogc29tZXdoYXQgaW1tdW5lIHRvIHVwc2V0cywgYWxsIHRoZSB3YXkgZG93biBpbiB0aGUgYm90dG9tIHJpZ2h0IG9mIHRoZSBncmFwaC4gVGVhbXMgbGlrZSBTdC4gSm9obidzIGFuZCBNaXNzb3VyaSB0aG91Z2gsIHdobyBleGNlbCBvbiBvbmUgZW5kIG9mIHRoZSBjb3VydCBhbmQgYXJlIHJlbGF0aXZlbHkgcGVkZXN0cmlhbiBvbiB0aGUgb3RoZXIsIGRvbid0IHNoYXJlIHRoYXQgbHV4dXJ5Lg0KDQo8YnI+IA0KDQpXZSd2ZSBkZXRlcm1pbmVkIHRoYXQgc2NvcmluZyBlZmZpY2llbmN5IG1hdHRlcnMgdG8gc29tZSBleHRlbnQsIGFzIGRvZXMgdGhlIGFtb3VudCBlYWNoIHRlYW0gc2NvcmVzIHBlciBzaG90LiBMZXQncyB0YWtlIHRob3NlIGNvbmNlcHRzIG5vdywgYW5kIGxvb2sgdG8gc2VlIGlmIHRoZXNlIHRlYW1zIGZpdCBpbnRvIGVpdGhlciBvZiB0aGUgInRlYW0gaWRlbnRpdGllcyIgd2UgbWVudGlvbmVkIGVhcmxpZXIuIEFjcm9zcyB0aGUgc3BvcnQgb2YgYmFza2V0YmFsbCwgdGhlIHRocmVlLXBvaW50ZXIgaGFzIGNvbXBsZXRlbHkgcmVzaGFwZWQgdGhlIHNjb3JpbmcgbGFuZHNjYXBlLiBQZXJoYXBzIHdlIGNhbiBzZWUgaWYgdGhlcmUncyBhIGRpc2NyZXBhbmN5IGJldHdlZW4gdGhlIHNsb3dlciwgbW9yZSBtZXRob2RpY2FsIHRlYW1zIHdobyB0cnkgdG8gY3JhZnQgdGhlIHBlcmZlY3Qgc2hvdCwgYW5kIHRoZSBtb3JlICJydW4gYW5kIGd1biIgc3R5bGUgb2YgcGxheS4gDQoNCmBgYHtyLCBmaWcuc2hvdz0naG9sZCcsIG91dC53aWR0aD0iNTAlIiwgd2FybmluZz1GQUxTRX0NCmdncGxvdChzdGF0czIsIGFlcyh4ID0gQWRqVCwgeSA9IHRocmVlcC5wZXJjLm9mZikpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiRBZGpUKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkdGhyZWVwLnBlcmMub2ZmKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9jYmJfdGVhbXMoZGF0YSA9IHN0YXRzMiwgYWVzKHRlYW0gPSB0ZWFtKSwgd2lkdGg9MC4wNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrDQogIGdnaGlnaGxpZ2h0KHRlYW0gJWluJSBjKCJDcmVpZ2h0b24iLCAiTmV3IE1leGljbyIsICJEcmFrZSIsICJBcmthbnNhcyIsICJNY05lZXNlIiwgIk1pY2hpZ2FuIiwgIk9sZSBNaXNzIiwgIkJZVSIsICJIb3VzdG9uIiwgIkZsb3JpZGEiKSkrDQogIHhsaW0obWluKHN0YXRzMiRBZGpUKSwgbWF4KHN0YXRzMiRBZGpUKSkrDQogIHlsaW0obWluKHN0YXRzMiR0aHJlZXAucGVyYy5vZmYpLCBtYXgoc3RhdHMyJHRocmVlcC5wZXJjLm9mZikpKw0KICBsYWJzKHggPSAiVGVhbSBBZGpUIiwNCiAgICAgICB5ID0gIlRlYW0gM1AlIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIEFkalQgdnMuIFRlYW0gM1AlIGZvciAiVW5kZXJkb2ciIFRlYW1zJykNCg0KZ2dwbG90KHN0YXRzMiwgYWVzKHggPSBBZGpULCB5ID0gdGhyZWVwLnBlcmMub2ZmKSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oc3RhdHMyJEFkalQpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiR0aHJlZXAucGVyYy5vZmYpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2NiYl90ZWFtcyhkYXRhID0gc3RhdHMyLCBhZXModGVhbSA9IHRlYW0pLCB3aWR0aD0wLjA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSsNCiAgZ2doaWdobGlnaHQodGVhbSAlaW4lIGMoIkxvdWlzdmlsbGUiLCAiTWFycXVldHRlIiwgIk1pc3NvdXJpIiwgIkthbnNhcyIsICJDbGVtc29uIiwgIlRleGFzIEEmTSIsICJJb3dhIFN0LiIsICJTdC4gSm9obidzIChOWSkiLCAiV2lzY29uc2luIiwgIkR1a2UiLCAiSG91c3RvbiIpKSsNCiAgeGxpbShtaW4oc3RhdHMyJEFkalQpLCBtYXgoc3RhdHMyJEFkalQpKSsNCiAgeWxpbShtaW4oc3RhdHMyJHRocmVlcC5wZXJjLm9mZiksIG1heChzdGF0czIkdGhyZWVwLnBlcmMub2ZmKSkrDQogIGxhYnMoeCA9ICJUZWFtIEFkalQiLA0KICAgICAgIHkgPSAiVGVhbSAzUCUiLA0KICAgICAgIHRpdGxlID0gJ1RlYW0gQWRqVCB2cy4gVGVhbSAzUCUgZm9yIFRlYW1zIFdobyBXZXJlICJVcHNldCInKQ0KYGBgDQoNCjxicj4NCg0KUmlnaHQgb2ZmIHRoZSBiYXQsIHRoaXMgZ3JhcGggZ2l2ZXMgdXMgYW4gZXhjZWxsZW50IGxvb2sgYXQgYSBjb3VwbGUgbWF0Y2h1cC1zcGVjaWZpYyBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRlYW1zLiBXZSBjYW4gc2VlIGEgZmV3IGNsZWFyIHRyZW5kcyByaWdodCBhd2F5LCB0aGF0IHNlZW0gdG8gaG9sZCB3aXRoIG91ciBlYXJsaWVyIGFzc3VtcHRpb25zLiBUaGUgZmlyc3Qgb2YgdGhlc2UgaXMgdGhhdCBoaWdoLXRlbXBvIHRlYW1zIHN0cnVnZ2xlIGFnYWluc3QgbG93IHRlbXBvIHRlYW1zLiBUaGlzIHdhcyBhIGNvbmNlcHQgSSBnZW5lcmFsbHkgZ3Jhc3BlZCBhbmQgaGFkIGJyb3VnaHQgdXAgYWxyZWFkeSwgYnV0IG5vdyB3ZSBjYW4gc2VlIGNsZWFybHkganVzdCBob3cgYmlnIG9mIGFuIGltcGFjdCBpdCBjYW4gaGF2ZS4gIzExIERyYWtlIHBsYXlzIGF0IGFuIGFic29sdXRlbHkgZ2xhY2lhbCBwYWNlLCBhdmVyYWdpbmcganVzdCA1OC44IHBvc3Nlc3Npb25zIHBlciBnYW1lLiBUaGV5J3JlIHRoZSBzbG93ZXN0IHRlYW0gaW4gdGhlIGNvdW50cnksIGFuZCB0aGF0IGNoYW5nZSBvZiBwYWNlIHdhcyBlbm91Z2ggZm9yIHRoZW0gdG8gdG9wcGxlIGEgZmFzdCBNaXNzb3VyaSB0ZWFtIHdobyBjb3VsZG4ndCBhZGp1c3QgdG8gZXNzZW50aWFsbHkgd2Fsa2luZyB1cCBhbmQgZG93biB0aGUgY291cnQuIFVuZm9ydHVuYXRlbHkgZm9yIERyYWtlLCB0aGV5IHJhbiBpbnRvIFRleGFzIFRlY2ggaW4gdGhlIFJvdW5kIG9mIDMyICh0aGUgcG9pbnQgb24gdGhlIGdyYXBoIHJpZ2h0IGFib3ZlIER1a2UpLiBUZXhhcyBUZWNoIGlzIGNvbWZvcnRhYmxlIHBsYXlpbmcgYXQgYSBzbG93ZXIgdGhhbiBhdmVyYWdlIHRlbXBvLCBhbmQgc2hvb3RzIG11Y2ggbW9yZSBlZmZpY2llbnRseSB0aGFuIERyYWtlLCBhdCBhIGhpZ2hlciB2b2x1bWUuIEZvciB0ZWFtcyB0aGF0IHBsYXkgYXQgYSBzaW1pbGFyIHRlbXBvLCB3aXRoaW4gMi0zIHBvc3Nlc3Npb25zIHBlciBnYW1lLCB0aGUgbW9yZSBlZmZpY2llbnQgdGVhbXMgYWxtb3N0IGFsd2F5cyB3aW4uIA0KDQpUaGVyZSBhcmUgb25seSB0aHJlZSBleGNlcHRpb25zIHRvIHRoaXMgcnVsZSBpbiBvdXIgcGxvdCwgb25lIG9mIHdoaWNoIHdlIGFscmVhZHkgZGVlbWVkIGEgY29pbiBmbGlwIGVhcmxpZXIgaW4gIzEgSG91c3RvbiB2cyAjMSBGbG9yaWRhLiBDb2luY2lkZW50YWxseSwgdGhvc2UgdHdvIGV4Y2VwdGlvbnMgYXJlIG91ciAiQ2luZGVyZWxsYSIgdGVhbXMuICoqT3Igc28gaXQgbWF5IHNlZW0uKiogQWxvbmcgd2l0aCBDbGVtc29uLCB3aG8gd2FzIHdpdGhvdXQgRGlsbG9uIEh1bnRlciBpbiB0aGVpciBmaXJzdCBhbmQgb25seSBnYW1lIGluIHRoZSB0b3VybmFtZW50LCBLYW5zYXMgd2FzIGFsc28gcGxheWluZyBzaG9ydGhhbmRlZC4gQnJpZWZseS4gTGVhZGluZyA2Ny02NCBvdmVyIEFya2Fuc2FzIHdpdGggMzoxMCBvbiB0aGUgY2xvY2ssIEpheWhhd2tzJyBzdGFyIGZvcndhcmQgS0ogQWRhbXMgdG9yZSBoaXMgYWNoaWxsZXMgYW5kIHdhcyBmb3JjZWQgdG8gbGVhdmUgdGhlIGdhbWUuIEluIHRoZSByZW1haW5pbmcgMyBtaW51dGVzIGFuZCAxMCBzZWNvbmRzIEFya2Fuc2FzIHdvdWxkIGdvIG9uIHRvIG91dHNjb3JlIEthbnNhcyAxNS01LCBjbG9zaW5nIG91dCB0aGUgZ2FtZSB3aXRoIGEgZmluYWwgc2NvcmUgb2YgNzktNzIgaW4gZmF2b3Igb2YgdGhlIFJhem9yYmFja3MuIE91dHNpZGUgb2YgdGhvc2UgdHdvIGluanVyeS1yZWxhdGVkIGFub21hbGllcywgYW5kIHRoZSBOYXRpb25hbCBDaGFtcGlvbnNoaXAgZ2FtZSwgb3VyIHJ1bGUgaG9sZHMgYWNyb3NzIGFsbCB0aGUgb3RoZXIgdXBzZXRzLiBXaGVuIHR3byBvdGhlcndpc2UgZXZlbmx5LW1hdGNoZWQgdGVhbXMgc3F1YXJlIG9mZiBhZ2FpbnN0IGVhY2ggb3RoZXIsIHRoZSB0ZWFtIHRoYXQncyBtb3JlIGVmZmljaWVudCBmcm9tIGJlaGluZCB0aGUgYXJjIGlzIGFsbW9zdCBhbHdheXMgZ29pbmcgdG8gd2luLiANCg0KWW91IGNhbiBpbnZlc3RpZ2F0ZSBhbGwgb2YgdGhpcyBmb3IgeW91cnNlbGYgdXNpbmcgdGhlIFtmbGV4ZGFzaGJvYXJkXShodHRwczovL2RpdmlkZW9uZS5zaGlueWFwcHMuaW8vZmxleGRhc2hib2FyZF9tbS8pIEkndmUgY3JlYXRlZCBmb3IgdGhpcyBkYXRhIGFzIHdlbGwuDQoNCiMgVGFrZWF3YXlzDQoNCk91ciB3aW4gcHJvYmFiaWxpdGllcyBnaXZlIHVzIGEgZ29vZCBpZGVhIG9mIGNsZWFyIHdpbm5lcnMuIEFueSB0ZWFtIHdpdGggYSA3MCUgY2hhbmNlIHRvIHdpbiBvciBiZXR0ZXIgd29uIGluIGFsbCBidXQgdGhyZWUgaW5zdGFuY2VzLiBUd28gb2YgdGhlc2Ugd2UgY2FuIGF0dHJpYnV0ZSB0byBpbmp1cmllcyBhZGRpbmcgYW4gZWxlbWVudCBvZiByYW5kb21uZXNzLCBhbmQgdGhlIHRoaXJkIHdlIGNhbiBhdHRyaWJ1dGUgdG8gYSAqdmFzdCogZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gdGVhbXMnIHNob290aW5nIGFiaWxpdHksIHdoaWNoIGlzIGp1c3QgcGFydCBvZiB0aGUgUmljayBQaXRpbm8gRXhwZXJpZW5jZS4gQW55IHRlYW0gd2l0aCBhIDMwJSBjaGFuY2UgdG8gd2luIG9yIGJldHRlciwgY2FuIHdpbi4gV2UgY2FuIGFsbW9zdCBwZXJmZWN0bHkgcHJlZGljdCB0aGUgb3V0Y29tZSBpbiB0aGVzZSBnYW1lcyBiYXNlZCBvbiB0d28gdGhpbmdzLiBUaGUgZmlyc3QgaXMgdGVtcG8sIG11Y2ggc2xvd2VyIHRlYW1zIGhvbGQgYW4gYWR2YW50YWdlIG92ZXIgdGVhbXMgdGhhdCBsaWtlIHRvIHBsYXkgZmFzdGVyIHRoYW4gYXZlcmFnZS4gVGhlIHNlY29uZCwgd2hlbiB0ZW1wbyBpcyBub3QgYSBxdWVzdGlvbiwgaXMgYDNQJWAuIFRlYW1zIHRoYXQgYXJlIGFibGUgdG8gc2NvcmUgdGhyZWVzIGF0IGEgaGlnaGVyIGNsaXAgdGhhbiB0aGVpciBvcHBvbmVudCBhbG1vc3QgYWx3YXlzIHdhbGsgYXdheSB3aXRoIGEgdmljdG9yeSBvdmVyIGxlc3MtZWZmaWNpZW50IHNob290aW5nLiBPdXIgbm90YWJsZSBleGNlcHRpb24gdG8gdGhpcyBpcyB0aGUgTmF0aW9uYWwgQ2hhbXBpb25zaGlwIGdhbWUsIHdoZXJlIHRoZSBiZXN0IG9mZmVuc2UgaW4gdGhlIGNvdW50cnkgZmFjZWQgb2ZmIGFnYWluc3QgdGhlIChzZWNvbmQpIGJlc3QgZGVmZW5zZSBpbiB0aGUgY291bnRyeS4gVGhlc2UgdGVhbXMgYXQgdGhlIHZlcnkgdG9wIG9mIG91ciBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSByYW5raW5ncyBzZWVtIHRvIGJlIGp1Z2dlcm5hdXRzIHdoZW4gbW92aW5nIHRocm91Z2ggYnJhY2tldCwgYW5kIHVudGlsIHRoZXkgbWVldCBhbiBvcHBvbmVudCB3aXRoIHNpbWlsYXIgYWJpbGl0eSwgdGhleSdyZSBnb2luZyB0byBlYXNpbHkgbWFrZSB0aGVpciB3YXkgdG93YXJkcyB0aGUgbGF0ZXIgcm91bmRzLiANCg0KSXQncyBpbXBvc3NpYmxlIHRvIHByZWRpY3QgaW5qdXJpZXMuIE5vIG1vZGVsIGNhbiBhY2NvdW50IGZvciB0aGF0IGV2ZW50IGluIHRoZSBtaWRkbGUgb2YgdGhlIHRvdXJuYW1lbnQuIEJ1dCB0aGF0J3MgdGhlIGJlYXV0eSBvZiBzb2x2aW5nIHRoZSAqTWFyY2ggTWFkbmVzcyogYnJhY2tldC4gU2ltcGx5IHB1dCwgbm9ib2R5IGtub3dzIHdoYXQncyBnb2luZyB0byBoYXBwZW4gYW5kIHRoZXJlJ3MgYW4gZWxlbWVudCBvZiByYW5kb21uZXNzIHRoYXQgY29tZXMgd2l0aCBtYWtpbmcgcGlja3MuIFNvbWUgbWF5IGV2ZW4gY2FsbCBpdCBsdWNrLiBJIHBvc2l0IHRoYXQgaWYgd2Ugd2VyZSB0byBsb29rIGF0IGV2ZXJ5IGluZGl2aWR1YWwgbWF0Y2h1cCBhbmQgYXBwbHkgb25seSB0aGUgcnVsZXMgY29tcGFyaW5nIGAzUCVgIHRvIGBBZGpUYCBpbiBjYXNlcyB3aGVyZSBjbG9zZWx5IG1hdGNoZWQgdGVhbXMgcGxheSBhdCBhIHNpbWlsYXIgc3BlZWQsIGFuZCBmYXZvcmluZyB0aGUgc2xvd2VyIHRlYW0gaWYgdGhleSBkb24ndCwgb3VyIGJyYWNrZXQgd291bGQgcHV0IHVwIHNvbWUgcmVhc29uYWJseSBzdWNjZXNzZnVsIHJlc3VsdHMuDQoNClJlZ2FyZGxlc3Mgb2YgdGhlIGluaGVyZW50IHJhbmRvbW5lc3MgdGhhdCBjb21lcyB3aXRoIGFueSBsaXZlIHNwb3J0aW5nIGV2ZW50LCB3ZSBjYW4gZGVmaW5pdGVseSBkcmF3IGEgbG90IG1vcmUgaW5zaWdodHMgZnJvbSB0aGlzIGFwcHJvYWNoIHRoYW4gSSBiZWdhbiB3aXRoLiBCeSBhcHBseWluZyB0aGlzIGNvbmNlcHQgb2YgInRlYW0gaWRlbnRpdGllcywiIHJhdGhlciB0aGFuIGJsaW5kbHkgZm9sbG93aW5nIGEgc2NvcmUgcHJlZGljdGlvbiwgSSB3b3VsZG4ndCBiZSBzdXJwcmlzZWQgaWYgdGhpcyBtb2RlbCwgd2hlbiBhcHBsaWVkIHdpdGggYSBuZXcsIGRlZXBlciB1bmRlcnN0YW5kaW5nIG9mIHRlYW0gbWF0Y2h1cHMsIHNlZXMgdXB3YXJkcyBvZiA2MC82NyBjb3JyZWN0IHBpY2tzLg0KDQpUaGVyZSdzIDQwIGRpZmZlcmVudCB2YXJpYWJsZXMgLSBzb21lIG1vcmUgaW1wb3J0YW50IHRoYW4gb3RoZXJzIC0gaW4gdGhpcyBkYXRhc2V0LiBJIGNvdWxkIHNpdCBoZXJlIGZvciB0aGUgbmV4dCBmZXcgbW9udGhzIG9mIG15IGxpZmUgaW52ZXN0aWdhdGluZyBlYWNoLCBidWlsZGluZyBhIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBhbGwgNDAgYW5kIHRyeWluZyB0byBmaXQgaXQgcGVyZmVjdGx5LiBBdCB0aGUgZW5kIG9mIHRoZSBkYXksIG5vdGhpbmcncyBnb2luZyB0byBhY2NvdW50IGZvciB0aGUgcmFuZG9tbmVzcy4gSW4gZmFjdCwgYW1vbmcgbXkgZnJpZW5kIGdyb3VwLCBkZXNwaXRlIGJlaW5nIGNvcnJlY3Qgb24gNTYvNjcgcGlja3MgY29tcGFyZWQgdG8gb3VyIHdpbm5lciB3aG8gYWNoaWV2ZWQgYSBzb2xpZCA1MS82NywgaWYgSSBoYWQgdXNlZCBvbmx5IHRoZSBzY29yZSBwcmVkaWN0aW9ucyBvZiB0aGlzIHBhcnRpY3VsYXIgbW9kZWwgSSB3b3VsZCd2ZSBjb21lIGluIGp1c3Qgc2l4dGggcGxhY2Ugb3V0IG9mIHRoZSBzaXh0ZWVuIG9mIHVzIGluIG91ciAiYnJhY2tldCBwb29sLiIgVGhlcmUsIHRoZSBzY29yaW5nIGZhdm9ycyB0aGUgRmluYWwgRm91ciBhbmQgQ2hhbXBpb25zaGlwIG11Y2ggbW9yZSBoZWF2aWx5IHRoYW4gdGhlIGVhcmxpZXIgcm91bmRzLiBPZiB0aGUgZml2ZSB3aG8gd291bGQndmUgYmVlbiBhaGVhZCBvZiBtZSwgdGhyZWUgb2YgdGhlbSBoYWQgYSBGaW5hbCBGb3VyIG9mIGFsbCB0aGUgIzEgc2VlZHMuIEFuIGV2ZW50IHRoYXQgcHJpb3IgdG8gdGhpcyB5ZWFyIGhhZCBvbmx5IG9jY3VycmVkIG9uY2UgaW4gdGhlIGhpc3Rvcnkgb2YgKk1hcmNoIE1hZG5lc3MqLCB3YXMgc2VlbWluZ2x5IGxpa2VseSBlbm91Z2ggZm9yIGFsbCB0aHJlZSB0byBwaWNrIGl0LiBPbiB0b3Agb2YgdGhhdCwgc2l4IG91dCBvZiB0aGUgc2l4dGVlbiBoYWQgRmxvcmlkYSB3aW5uaW5nIGl0IGFsbCwgYnV0ICoqdGhlcmUncyByYW5kb21uZXNzIGluIHRoYXQgbm9ybWFsY3kqKi4gUGVyaGFwcyBpdCdzIGFuIGluZGljYXRpb24gdGhhdCB0aGUgc2VsZWN0aW9uIGNvbW1pdHRlZSBpcyBnZXR0aW5nIG11Y2ggYmV0dGVyIHdpdGggdGhlaXIgc2VlZGluZywgYW5kIHRoZSBjaGFvcyB3aWxsIHN0YXJ0IHRvIHZhbmlzaCBmcm9tIHRoZSB0b3VybmFtZW50PyBNYXliZSBOSUwgaXMgdG8gYmxhbWUsIGFuZCBjb2xsZWdlIGJhc2tldGJhbGwgaXMgZG9vbWVkIHRvIHNlZSB0aGVzZSBtb3JlIGRvbWluYW50IHRlYW1zIHJ1biB0aGUgdG91cm5hbWVudCBlYWNoIHllYXIuIFdobyBrbm93cz8gSSBjZXJ0YWlubHkgZG9uJ3QsIGJ1dCBJJ2xsIHN0aWxsIGJlIHJpZ2h0IGhlcmUgbWFraW5nIG15IHBpY2tzIGluIE1hcmNoIGFsb25nIHdpdGggbWlsbGlvbnMgb2Ygb3RoZXJzLg0KDQotLS0NCg0KIyBBYm91dCBNZQ0KDQo8YnI+DQoNCjxkaXYgc3R5bGU9ICJmbG9hdDpsZWZ0O3Bvc2l0aW9uOiByZWxhdGl2ZTsgcmlnaHQ6IDMwcHg7IHRvcDogLTdweDsiPg0KYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoID0gIjE3NXB4IiwgZmlnLmFsaWduPSdsZWZ0J30NCg0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3BvcnRmb2xpb2ltYWdlLmpwZycpIA0KDQpgYGANCjwvZGl2Pg0KDQpJIGFtIGEgZmlyc3QgeWVhciBncmFkdWF0ZSBzdHVkZW50IHB1cnN1aW5nIG15IG1hc3RlcidzIGRlZ3JlZSBpbiBEYXRhIFNjaWVuY2UgYW5kIEFuYWx5dGljcyBhdCBDbGVtc29uIFVuaXZlcnNpdHkuIEFzIHRoZSBtaWRkbGUgb2Ygc2V2ZW4gY2hpbGRyZW4gd2hvIGFsbCBwdXJzdWVkIGRpZmZlcmVudCBhY3Rpdml0aWVzIGdyb3dpbmcgdXAgb3V0c2lkZSBvZiBQaGlsYWRlbHBoaWEsIHNwb3J0cyBoYXZlIGFsd2F5cyBiZWVuIGEgZm9jYWwgcG9pbnQgaW4gbXkgbGlmZS4gQXBwbHlpbmcgc3RhdGlzdGljcyB0byBzcG9ydHMgb3BlbmVkIG15IGV5ZXMgdG8gdGhlIHBvd2VyIG9mIGRhdGEsIGFuZCBicm91Z2h0IG1lIHRvIHdoZXJlIEkgYW0gdG9kYXkuIFRoZSAqTWFyY2ggTWFkbmVzcyogYnJhY2tldCBpbiBwYXJ0aWN1bGFyIGlzIGEgY2hhbGxlbmdlIHRoYXQgSSB3b3VsZCBsb3ZlIHRvIGNvbnRpbnVlIHRvIHRha2Ugb24gaW4gb3JkZXIgdG8gYnVpbGQgbXkgdG9vbCBzZXQgYXMgSSBkaXZlIGRlZXBlciBpbnRvIHRoaXMgZmllbGQuIFNvbWUgb2YgdGhlIGJlc3QgYW5kIGJyaWdodGVzdCBoYXZlIGNvbnRyaWJ1dGVkIHRoZWlyIG1pbmRzIHRvIHByZWRpY3RpbmcgdGhlIG91dGNvbWUgb2YgdGhpcyB0b3VybmFtZW50LCBhbmQgbm9uZSBoYXZlIHN1Y2NlZWRlZCBzbyBmYXIuIFByb2JsZW1zIGxpa2UgdGhpcyBhcmUgd2hhdCBkcml2ZXMgbXkgcGFzc2lvbiBmb3IgbGVhcm5pbmcsIGFuZCBJIGhvcGUgdG8gY29udGludWUgdG8gYm90aCBmaW5kIGFuZCBzb2x2ZSB0aGVzZSBwcm9ibGVtcyBhcyBJIG1vdmUgdG93YXJkcyBlYXJuaW5nIG15IGRlZ3JlZSBhbmQgb3V0IGludG8gdGhlIHdvcmxkLg0KDQo8YnI+DQoNCi0tLQ0KDQojIFJlZmVyZW5jZXMNCg0KKiBCZWxsQ3VydmUgLSBodHRwczovL3d3dy5yYXdidy5jb20vfmRlYW5vL2FydGljbGVzL0JlbGxDdXJ2ZS5odG1sDQoqIEtlblBvbSAtIGh0dHBzOi8va2VucG9tLmNvbS8NCiogRGF0YSBBY3Rpb24gTGFiIC0gaHR0cHM6Ly93d3cuZGF0YS1hY3Rpb24tbGFiLmNvbS8yMDIxLzExLzIxL3ByZWRpY3RpdmUtYW5hbHl0aWNzLWluLWNvbGxlZ2UtYmFza2V0YmFsbC8NCiogZ2dwbG90MjogRWxlZ2FudCBHcmFwaGljcyBmb3IgRGF0YSBBbmFseXNpcyAoM2UpIC0gaHR0cHM6Ly9nZ3Bsb3QyLWJvb2sub3JnLw0KKiBFU1BOIC0gaHR0cHM6Ly93d3cuZXNwbi5jb20vbWVucy1jb2xsZWdlLWJhc2tldGJhbGwvYnJhY2tldA0KKiBNb3VudCBTdC4gTWFyeSdzIC0gaHR0cHM6Ly9tc21hcnkuZWR1L2Fib3V0L3F1aWNrZmFjdHMuaHRtbA0KKiBNYXRoZW1hdGljcyBpbiBSIE1hcmtkb3duIC0gaHR0cHM6Ly9ycHJ1aW0uZ2l0aHViLmlvL3MzNDEvUzE5L2Zyb20tY2xhc3MvTWF0aGluUm1kLmh0bWwNCiogTkNBQSAtIGh0dHBzOi8vd3d3Lm5jYWEuY29tL25ld3MvYmFza2V0YmFsbC1tZW4vYnJhY2tldGlxLzIwMjUtMDMtMjMvbG9uZ2VzdC1uY2FhLWJyYWNrZXQtaGFzLWV2ZXItc3RheWVkLXBlcmZlY3QNCiogTkNBQSBTdGF0aXN0aWNzIC0gaHR0cHM6Ly9zdGF0cy5uY2FhLm9yZy9zZWxlY3Rpb25fcmFua2luZ3Mvbml0dHlfZ3JpdHRpZXMvMzA5Njg/dXRmOD0lRTIlOUMlOTMmY29tbWl0PVN1Ym1pdA0KKiBUZWFtUmFua2luZ3MgLSBodHRwczovL3d3dy50ZWFtcmFua2luZ3MuY29tLw0KKiBUaGUgUG93ZXIgUmFuayAtIGh0dHBzOi8vdGhlcG93ZXJyYW5rLmNvbS9jYmItYW5hbHl0aWNzLw0KKiBBcmthbnNhcyBGaWdodCAtIGh0dHBzOi8vd3d3LmFya2Fuc2FzZmlnaHQuY29tLzIwMTkvMTAvMjIvMjA5MjU3NDAvYXJrYW5zYXMtZmlnaHRzLWdsb3NzYXJ5LW9mLWFkdmFuY2VkLWJhc2tldGJhbGwtc3RhdHMjOn46dGV4dD1SZWJvdW5kcyUyMGFuZCUyMHR1cm5vdmVycyUyQyUyMG1vc3RseS4sZWZmZWN0aXZlJTIwcG9zc2Vzc2lvbiUyMHJhdGlvJTIwKEVQUikuDQoqIFI0RFMgKDJlKSAtIGh0dHBzOi8vcjRkcy5oYWRsZXkubnovDQoqIFN0YWNrT3ZlcmZsb3cgLSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NTQzMzIwOS91c2luZy1hLXNoaW55LWlucHV0LWFzLWFuLWFyZ3VtZW50LW9mLWEtZnVuY3Rpb24NCiogUGxvdHRpbmcgTm9ybWFsIERpc3RyaWJ1dGlvbnMgLSBodHRwczovL3NlYmFzdGlhbnNhdWVyLmdpdGh1Yi5pby9ub3JtYWxfY3VydmVfZ2dwbG90Mi8NCg==